P2512
[HAOI2008]糖果传递
题目描述
有 \(n\) 个小朋友坐成一圈,每人有 \(a_i\) 个糖果。每人只能给左右两人传递糖果。每人每次传递一个糖果代价为 \(1\)。
输入格式
小朋友个数 \(n\),下面 \(n\) 行 \(a_i\)。
输出格式
求使所有人获得均等糖果的最小代价。
样例 #1
样例输入 #1
4
1
2
5
4
样例输出 #1
4
提示
对于 \(100\%\) 的数据 \(n\le 10^6\)。
神仙题
不妨假设每个人只往左边传递糖果
第i个人往左边传递的数目为Xi
那么 有:
X2-X1+A1=ave
X3-X2+A2=ave
……
Xn-Xn-1+An-1=ave
代入X1有
X2=X1-(A1-ave)
X3=X2-(A2-ave)=X1-(A1-ave)-(A2-ave)
……
Xn=X1-(A1-ave)-…-(An-1-ave)
设Ci=(A1-ave)+…+(Ai-1-ave)
则有X2=X1-c2 …Xn=Xn-1-Cn
要使总代价最小即
min{|X1|+|X2|+…+|Xn|}
代入即min{|X1-C1|+|X1-C2|+…+|X1-Cn|}
取Ci的中位数mid即可最小化代价
点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
int n,a[1000005],ave,c[1000005];
signed main()
{
ios::sync_with_stdio(false);
cin>>n;
for(int i=1;i<=n;i++)cin>>a[i],ave+=a[i];
ave/=n;
for(int i=1;i<=n;i++)
c[i]=c[i-1]+ave-a[i-1];
sort(c+1,c+n+1);
int mid=c[(n+1)/2];
int tot=0;
for(int i=1;i<=n;i++)
tot+=abs(mid-c[i]);
cout<<tot<<"\n";
return 0;
}
此生无悔入OI 来生AK IOI

浙公网安备 33010602011771号