[HAOI2008] 糖果传递

洛谷P2512 [HAOI2008] 糖果传递

考虑相似题目均分纸牌

当每个人没有做成一个圈,也就是考虑在一个序列上的转移,我们规定每个人只向他后面的人传递糖果,比如,第一第二两人持有的糖果数分别为\(A_1\) \(A_2\),我们要将糖果数均分为k,那么第一个人要向第二个人传递\(C_1=A_1-k\)个糖果,第二个人要向第三个人传递\(C_2=A_2+C_1-k\)个糖果

显然,这个做法是正确的,当我们的第一个人向第二个人传递\(C_1\)个糖果时,第一个人的糖果数等于k,我们只需要考虑从第二个人开始后面的人去均分糖果,同样,当我们第二个人转移后,我们只需要考虑第三个人之后,直到均分整个序列

重新思考环形时的解法

我们可以先断开一条边形成一个序列,假设现在有n个人围成一个环,我们设第i个人持有的糖果数为\(A_i\),均分后的糖果数为k
我们设$$C_i=C_{i-1}+A_i-k (i>1),C_1=C_n+A_1-k$$
即第i个人向第i+1个人转移的糖果数,将上式推为

\[C_1=C_n+A_1-k \]

\[C_2=C_1+A_2-k=C_n+A_1+A_2-2k \]

\[C_3=C_2+A_3-k=C_n+A_1+A_2+A_3-3k \]

\[. \]

\[. \]

\[. \]

\[C_n=C_{n-1}+A_1+A_2+...+A_{n-1}-nk \]

我们发现,\(C_i\)的后几项格式相同,我们就可以设

\[P_i=\sum_{j=1}^{j<=i}A_j-i*k \]

这时,我们就可以将上式改为

\[C_i=P_i+C_n \]

最终答案就为

\[ans=\sum_{i=1}^{i<=n}|C_i|=\sum_{i=1}^{1<=n}|P_i+C_n| \]

我们可以将上式理解为\(C_n\)\(P_{1<=i<=n}\)的距离之和,很显然,\(C_n\)取C中的中位数就行
我们将C数组与P数组预处理出来,求出C的中位数,计算答案即可

using namespace std;
#define ll long long
#define MAXN 1000010
inline ll read(){
	ll x=0,f=1;
	char c=getchar();
	while(c<'0'||c>'9'){
		if(c=='-')f=-1;
		c=getchar();
	}
	while(c>='0'&&c<='9'){
		x=x*10+c-'0';
		c=getchar();
	}
	return x*f;
}
ll a[MAXN],p[MAXN],c[MAXN];
ll n,k,s,ans;
pair <ll,ll> q[MAXN];
int main(){
	n=read();
	for(int i=1;i<=n;i++){
		k+=a[i]=read();
	}
	k/=n;
	for(int i=1;i<=n;i++){
		c[i]=a[i]-k;
		p[i]=p[i-1]+a[i]-k;
	}
	sort(p+1,p+1+n);
	s=p[(n+1)/2];
	for(int i=1;i<=n;i++){
		ans+=abs(p[i]-s);
	}
	cout<<ans<<endl;
	return 0;
}
posted @ 2024-11-26 22:16  flyfreemrn  阅读(9)  评论(0)    收藏  举报