糖果传递 (环状的均分纸牌)

 糖果传递 (环状的均分纸牌)

Description

有n个小朋友坐成一圈,每人有ai个糖果。每人只能给左右两人传递糖果。每人每次传递一个糖果代价为1。

Input

小朋友个数n 下面n行 ai

Output

求使所有人获得均等糖果的最小代价。

Sample Input

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\n",x);
    return 0;
}

 

posted @ 2017-03-18 14:50  枫虹  阅读(930)  评论(0编辑  收藏  举报