首页 > 其他分享 >ABC 313C Approximate Equalization 2

ABC 313C Approximate Equalization 2

时间:2024-06-03 17:10:16浏览次数:23  
标签:ABC maxnum int sum Equalization Approximate much1 数组 pj

题意
现在给出一个数组a[n],现在你可以进行这种操作:

  • 选择i,j(1<=i,j<=n),使得a[i]=a[i]-1,a[j]=a[j]+1
    现在你可以进行无限次这种操作,现在需要你求出最少次数,使得数组中的最大值与最小值之间的差不超过1。

思路
我们考虑到每一次操作可以使得数组中的一个数加一,另一个数减一,那么无论你进行多少次操作,这个数组的和是不会变的。那么我们现在考虑到最后的情况:

  1. 数组中的所有数全部相同,并且等于数组的平均数(sum%n==0)
  2. 数组中有一些数是平均数,另一部分是平均数加1(sum%n!=0)

那么根据这个结论我们可以直接展开模拟了。我们用much1=sum%n。表示有多少项是等于sum/n+1的。然后扫一遍数组,把原本就等于sum/n+1的数字给去除,剩下的有两种情况:

  1. much1小于数组中原本等于sum/n+1的个数,那么余下的sum/n+1以及大于sum/n+1的数就全部变成sum/n,可以证明的是,将这些数全部变成sum/n的代价就是我们的答案
  2. much1大于等于数组中原本等于sum/n+1的个数,那么我们先扫一遍原数组,把大于sum/n+1的数全部变为sum/n+1,并计算代价。那么接下来又有两种情况。第一种情况是much1==0,那么剩下的大于sum/n+1的数就必须要变成sum/n,将这个代价加上前者,就是我们最后的答案。第二种情况是much1还有剩余,那么这个时候就得让小于等于sum/n的数变成sum/n+1了,我们可以先将这些数变成sum/n,然后算出代价后再加上余下的much1,这就是最后的答案。

代码

int n;
cin>>n;
int maxnum=-1e18;
int minnum=1e18;
int sum=0;
for(int i=1;i<=n;i++)
{
	cin>>a[i];
	maxnum=max(maxnum,a[i]);
	minnum=min(minnum,a[i]);
	sum+=a[i];
}
if(maxnum-minnum<=1)
{
	cout<<0<<endl;
	return 0;
}
int much1=sum%n;
int pj=sum/n;
//cout<<pj<<" "<<much1<<endl;
if(much1==0)
{
	int much=0;
	for(int i=1;i<=n;i++) much+=abs(a[i]-pj);
	cout<<much/2<<endl;
}
else
{
	int muchs=0;
	int muchx=0;
	for(int i=1;i<=n;i++) 
	{
		if(a[i]==pj+1)
	  {
	  	much1--;
	  	if(much1==0) break;
	  }
	}
	if(much1==0)
	{
		for(int i=1;i<=n;i++)
		{
			if(a[i]>pj&&a[i]!=pj+1) muchx+=a[i]-pj;
			else if(a[i]<pj) muchs+=pj-a[i];
		}
		cout<<muchx<<endl;
	}
	else
	{
		for(int i=1;i<=n;i++)
		{
			if(much1>0&&a[i]>pj+1)
			{
				much1--;
				muchx+=a[i]-pj-1;
				a[i]=pj+1;
			}
			if(!much1) break;
		}
		if(!much1)
		{
			for(int i=1;i<=n;i++) if(a[i]>pj+1) muchx+=a[i]-pj;
			cout<<muchx<<endl;
			return 0;
		}
		else 
		{
			for(int i=1;i<=n;i++) if(pj>a[i]) muchs+=pj-a[i];
			muchs+=much1;
			cout<<muchs<<endl;
			return 0;
		}
	}
}

return 0;} 

标签:ABC,maxnum,int,sum,Equalization,Approximate,much1,数组,pj
From: https://www.cnblogs.com/lulu7/p/18229269

相关文章

  • [ABC238E] Range Sums
    原题链接题解把这里的数字看成间隔,不要看成点假设已知能和\(l\)组成区间的端点集合\(A\)和以\(r\)组成区间的端点集合\(B\),这时候加入一个以\(l,r\)为左右端点的区间,那么在加入区间\(l,r\)之后,这两个集合可以合并code#include<bits/stdc++.h>usingnamespacestd......
  • abc356
    D1.5h没做出,E0.5h做出来啦?E有两个做法,第一个是枚举分子来计算分母对答案的贡献,另一种是枚举分母来求分子对答案的贡献。枚举分子来计算分母对答案的贡献需要用到数论分块,所以我们讲枚举分母来求分子对答案的贡献的写法。我们可以直接去枚举这个数是分母的情况。我们先考虑用......
  • ABC 312D题 Count Bracket Sequences
    题意给定一个非空的字符串,其由(,),?三个字符构成,其中?可以被(或者)给替换掉,求替换后的字符串是符合括号匹配的情况下的方案数。最后答案对mod=998244353取模思路应该算是一个板题,一开始的想法是往卡特兰数的方向思考,但是可能是我太水了没想出来,然后一想到卡特兰数的dp求法,就......
  • Atcoder ABC355 C~F
    C出题人太善良了,加强到\(10^5\)都没问题。考虑维护每条横线竖线两条对角线上被标记的点的个数,每次标记点后,判断是否有线上点全被标记。再考虑如何将点编号转为坐标,记编号为\(t\),推柿子:\[(x-1)\timesn+y=t\]\[nx+y=t+n\]\[x=\frac{t+n-y}{n}\]等同于找到\(y\)使得:\[n......
  • ABC 354
    B-AtCoderJanken2本来想开\(\rmvector<pair<string,int>>\)的,但发现其实没有必要,整数部分只需求和即可。另外,多个字符串按字典序升序排序可以直接存\(\rmvector\)后\(\rmsort\)。#include<bits/stdc++.h>usingnamespacestd;usingi64=longlong;intmai......
  • 「杂题乱刷」 AT_abc285_e
    好题。直接上代码吧。点击查看代码/*Tips:你数组开小了吗?你MLE了吗?你觉得是贪心,是不是该想想dp?一个小时没调出来,是不是该考虑换题?打cf不要用umap!!!记住,rating是身外之物。该冲正解时冲正解!Problem:算法:思路:*/#include<bits/stdc++.h>usingnamespacest......
  • TabControl和TabItem的样式自定义:为什么要使用自定义模板?
    在WPF(WindowsPresentationFoundation)中,控件的外观和行为是通过控件模板(ControlTemplate)来定义的。TabControl和TabItem控件也不例外,它们的默认控件模板定义了这些控件的结构和视觉状态。在实际应用中,开发者可能会发现直接设置TabItem的某些属性(例如Background)时不会生效。这篇......
  • 实现Avalonia平台下低配版的Dock控件:实现TabControl的可关闭
    在弄一个项目,在WPF下用Dock控件,在Avalonia平台下实现也有一个Dock控件,但用起来有点复杂。Install-PackageDock.AvaloniaInstall-PackageDock.Model.Mvvm感兴趣的可以访问网站了解:https://github.com/wieslawsoltes/Dock其实本身用的比较简单,所以就想着,用TabControl来改一下......
  • ABC355
    E将所有的下标作为点,建一张无向图。当且仅当可以询问\([l,r]\)时,在点\(l\)和\(r+1\)之间连一条边。可以发现能求出\([L,R]\)的和等价于\(L\)与\(R+1\)连通,且最少询问次数等于两点间最短路径边数。具体实现是容易的。F边权很小,提示我们可以暴力枚举和替换边。开......
  • abc 355 F - MST Query
    题目链接:https://atcoder.jp/contests/abc355/tasks/abc355_f题目要求动态维护最小生成树.那么我们考虑朴素的Kruskal算法:将边从小到大排序,不断加边,用并查集维护联通块,加边加到整张图联通(联通块数量为1)为止,最后的答案就是从小到大遍历边权将边的数量*当前边权相加起来......