[HAOI2008]糖果传递
题目描述
有n个小朋友坐成一圈,每人有ai个糖果。每人只能给左右两人传递糖果。每人每次传递一个糖果代价为1。
输入输出格式
输入格式:小朋友个数n 下面n行 ai
输出格式:求使所有人获得均等糖果的最小代价。
输入输出样例
说明
对于100%的数据 n≤106n\le 10^6n≤106
首先每个人最后的糖果数是可以计算出来的,我们记其为$M$。
假设有$4$个人,编号$1$~$4$,第$i$个人初始糖果数量为$A_i$,设$1->4$糖果数为$x_1$(符号代表给出还是收入),那么我们对于标号为$1$的人很容易得到一个等式$M=A_1-x_1+x_2$。
对于所有人我们都可以得到这样的一个等式,一共有$n$个变量,但可惜我们发现其实有效的等式只有只有$n-1$个(因为任意$n-1$个等式都可以推出剩下的一个等式)。
我们无法求出答案,但我们可以试着用一个变量表示其他的变量,以$x_1$为例;
对于第一个人,$A_1-x_1+x_2=M => x_2=M-A_1+x_1=x_1-C_1$(令$C_1=A_1-M$)
对于第二个人,$A_2-x_2+x_3=M => x_3=M-A_2+x_2=2M-A_1-A_2+x_1=x_1-C_2$(令$C_2=C_1+A_2-M$)
……
对于第$n$个人,$A_n-x_n+x_1=M$,这个是多余的,舍去。
依题,我们要求$$\sum_{i=1}^N Abs(x_i)$$
对于刚才的推导,就是$$\sum_{i=1}^N Abs(x_1-C_i)$$
转化为数学模型就是数轴上所有点到一个点的距离。
那么原题就是找到一个点,使得所有点到其距离和最短,显然找到一个中间点即可。
附上巨佬的原文链接http://www.cnblogs.com/NaVi-Awson/p/7520039.html
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 long long a[1000001],c[1000001],n,ans,sum,m; 7 int main() 8 {int i; 9 cin>>n; 10 for (i=1;i<=n;i++) 11 scanf("%lld",&a[i]),sum+=a[i]; 12 m=sum/n; 13 for (i=1;i<=n;i++) 14 c[i]=a[i]+c[i-1]-m; 15 sort(c+1,c+n+1); 16 long long pos=c[n/2]; 17 for (i=1;i<=n;i++) 18 ans+=abs(c[i]-pos); 19 cout<<ans; 20 }