「BZOJ3293」[CQOI2011] 分金币
Description
圆桌上坐着n个人,每人有一定数量的金币,金币总数能被n整除。每个人可以给他左右相邻的人一些金币,最终使得每个人的金币数目相等。你的任务是求出被转手的金币数量的最小值。
Input
第一行为整数n(n>=3),以下n行每行一个正整数,按逆时针顺序给出每个人拥有的金币数。
Output
输出被转手金币数量的最小值。
Sample Input
4
1
2
5
4
Sample Output
4
样例解释
设四个人编号为1,2,3,4。第3个人给第2个人2个金币(变成1,4,3,4),第2个人和第4个人分别给第1个人1个金币。
HINT
N<=<=100000,总金币数<=10^9
题解
白书p4
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; int n,a[100001]; long long c[100001]; long long tot,ans; inline int read() { char ch=getchar(); int f=1,x=0; while(!(ch>='0'&&ch<='9')){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+(ch-'0');ch=getchar();} return x*f; } int main() { n=read(); for(int i=1;i<=n;i++) { a[i]=read(); tot+=a[i]; } tot/=n; for(int i=2;i<=n;i++) c[i]=c[i-1]+(a[i-1]-tot); sort(c+1,c+n+1); int tmp=c[(n+1)/2]; for(int i=1;i<=n;i++) ans+=abs(tmp-c[i]); printf("%lld",ans); return 0; } |
Subscribe