糖果传递 (环状的均分纸牌)
Description
有n个小朋友坐成一圈,每人有ai个糖果。每人只能给左右两人传递糖果。每人每次传递一个糖果代价为1。
Input
小朋友个数n 下面n行 ai
Output
求使所有人获得均等糖果的最小代价。
Sample Input
4
1
2
5
4
1
2
5
4
Sample Output
4
HINT
数据规模
30% n<=1000
100% n<=100000
/* 环状均分纸牌 显然最后每个人都剩下sum/n张纸牌,p[i]表示这个人给下一个人多少张纸牌 显然p[i]=a[i]+p[i-1]-sum/n p[i]-p[i-1]=a[i]-sum/n,所以p[i]-p[i-1]+p[i-1]-p[i-2]+.....-p[1] = sigma(i)(a[i]-sum/n) 即p[i]=sigma(i)(a[i]-sum/n)+p[1] 显然sigma(i)(a[i]-sum/n)是定值,所以p[1]是所有sigma(i)(a[i]-sum/n)的中位数就好了 …................................................................................................................................. 我们用xi表示第i个小朋友给第i−1个小朋友的糖果数,其中x1表示第1个小朋友给第n个朋友的糖果数,那么最终答案即为|x1|+|x2|+...|xn|。 我们假设最后每个人剩avg个糖果,那么可以得到: 对于第一个小朋友:a1+x2−x1=avg 对于第二个小朋友:a2+x3−x2=avg … 对于最后一个小朋友:an+x1−xn=avg 整理一下即可得到: x2=avg−a1+x1 x3=avg−a2+x2=2avg+x1−a2−a1 … xn=avg−an−1+xn−1=(n−1)avg+x1−∑n−1i=1ai 我们令ci=∑ij=1ai+i×avg,上述式子即可转化为求解|x1|+|x1−c1|+|x1−c2|...+|x1−cn−1|的最小值,那么直接令x1等于c的中位数即可。 */ #include<iostream> #include<algorithm> #include<cmath> #include<cstdio> using namespace std; int a[1000005],c[1000005]; int main() { int n; cin>>n; long long sum=0,x=0,m; for(int i=1;i<=n;i++) { scanf("%d",&a[i]); sum+=a[i]; } m=sum/n; for(int i=2;i<=n;i++) c[i]=c[i-1]+a[i]-m; sort(c+1,c+n+1); for(int i=1;i<=n;i++) x+=abs(c[i]-c[(n+1)/2]); printf("%lld ",x); return 0; }