bzoj3293[Cqoi2011]分金币
Description
圆桌上坐着n个人,每人有一定数量的金币,金币总数能被n整除。每个人可以给他左右相邻的人一些金币,最终使得每个人的金币数目相等。你的任务是求出被转手的金币数量的最小值。
Input
第一行为整数n(n>=3),以下n行每行一个正整数,按逆时针顺序给出每个人拥有的金币数。
Output
输出被转手金币数量的最小值。
Sample Input
4
1
2
5
4
1
2
5
4
Sample Output
4
样例解释
设四个人编号为1,2,3,4。第3个人给第2个人2个金币(变成1,4,3,4),第2个人和第4个人分别给第1个人1个金币。
样例解释
设四个人编号为1,2,3,4。第3个人给第2个人2个金币(变成1,4,3,4),第2个人和第4个人分别给第1个人1个金币。
HINT
N<=<=100000,总金币数<=10^9
可以发现只要确定了n给1的金币数,就可以确定所有人之间给的金币数,设n给1的金币数为x,写出总金币数关于x的函数,是一个绝对值函数,有几何意义,一个是一个初中就会的简单求最值,取中位数作为x就是最小值。
1 program coin(input,output); 2 var 3 a,b:array[0..100010]of int64; 4 n,i:longint; 5 c,t,ans:int64; 6 procedure sort(q,h:longint); 7 var 8 i,j:longint; 9 x,t:int64; 10 begin 11 i:=q;j:=h;x:=b[(i+j)>>1]; 12 repeat 13 while b[i]<x do inc(i); 14 while x<b[j] do dec(j); 15 if i<=j then 16 begin 17 t:=b[i];b[i]:=b[j];b[j]:=t; 18 inc(i);dec(j); 19 end; 20 until i>j; 21 if j>q then sort(q,j); 22 if i<h then sort(i,h); 23 end; 24 begin 25 assign(input,'coin.in');assign(output,'coin.out');reset(input);rewrite(output); 26 readln(n); 27 c:=0; 28 for i:=1 to n do begin readln(a[i]);c:=c+a[i]; end; 29 c:=c div n; 30 b[1]:=0; 31 for i:=2 to n do b[i]:=b[i-1]+c-a[i-1]; 32 sort(1,n); 33 t:=b[(1+n)>>1];ans:=0; 34 for i:=1 to n do ans:=ans+abs(t-b[i]); 35 write(ans); 36 close(input);close(output); 37 end.