Description
有n个小朋友坐成一圈,每人有ai个糖果。每人只能给左右两人传递糖果。每人每次传递一个糖果代价为1。
Input
第一行一个正整数n<=987654321,表示小朋友的个数.接下来n行,每行一个整数ai,表示第i个小朋友得到的
糖果的颗数.
Output
求使所有人获得均等糖果的最小代价。
Sample Input
1
2
5
4
Sample Output
我们令 ave = segma(ai) / n (1<=i<=n)
一个小盆友向左右两人都可传递糖果,是双向的,我们就可以用正负来表示方向~,这样我们就可以变成“单向”的形式
我们设第i个小盆友向第i-1个小盆友传递了xi个糖果(xi为正,表示第i个小盆友给第i-1个小盆友糖果,i为负表示第i-1个小盆友给第i个小盆友糖果~)
那么,ans=|x1|+|x2|+...+|xn| (注意是绝对值的和)
那么对于每一个小盆友我们有ai-xi+xi+1=ave
我们可以得到n个这样的方程,但是我们是无法直接解出答案的_(:з」∠)_
由于是最值问题,我们考虑单变量的最值问题,我们尝试用x1表示其他的xi
a1-x1+x2=ave -> x2=ave-a1+x1
a2-x2+x3=ave -> x3=ave-a2+x2=ave-a2+ave-a1+x1
......
an-xn+x1=ave -> xn=segma(ave-ai)+x1 (1<=i<=n-1)
由于ave 与 ai 为常数,所以我们用ci表示
即c1=ave-a1,c2=ave-a2+ave-a1, ...,cn=segma(ave-ai) (1<=i<=n-1)
那么,ans=|x1|+|x2|+..+|xn|=|x1|+ |c1+x1| + |c2+x1| +...+| cn+x1|
因为 |ci+x1|=|ci-(-x1)|
所以 ans=|x1|+|c2-(-x1)|+...+|cn-(-x1)|
此时,我们很容易想到中位数的一个性质:
有一列数X1,X2,X3,...,Xn,
f(x)=|X1-x|+|X2-x|+|X3-x|+...+|Xn-x|,当x=数列中位数时,f(x)最小
所以,当-x1=c数组组成的数列的中位数时,ans最小================我是理想与现实的分界线_(:з」∠)_ ================
所以我们在计算ci的时候直接取负就好了
即:c1 = a1-ave , c2 = a2-ave + a1-ave , ... , cn=segma(ai-ave) (1<=i<=n-1)
所以 x2 = c1-x1 , x3 = c2-x1,... ,xn = cn-x1
我们令x1=c数组的中位数 算出 ans=|x1|+|c1-x1|+|c2-x1|+....+|cn-x1| 即可
var
n,median,ave :longint;
sum,ans :int64;
a,c :array[0..1000010] of longint;
i :longint;
procedure sort(l,r: longint);
var
i,j,x,y: longint;
begin
i:=l;
j:=r;
x:=c[(l+r) div 2];
repeat
while c[i]<x do inc(i);
while x<c[j] do dec(j);
if not(i>j) then
begin
y:=c[i];c[i]:=c[j];c[j]:=y;
inc(i);j:=j-1;
end;
until i>j;
if l<j then sort(l,j);
if i<r then sort(i,r);
end;
begin
read(n);sum:=0;
for i:=1 to n do read(a[i]);
for i:=1 to n do inc(sum,a[i]);
ave:=sum div n;
c[1]:=0;
for i:=2 to n do c[i]:=a[i]-ave+c[i-1];
sort(1,n);
ans:=0;
if (n mod 2=1) then median:=c[n div 2+1]
else median:=(c[n div 2]+c[n div 2+1]) div 2;
for i:=1 to n do inc(ans,abs(median-c[i]));
writeln(ans);
end.
—— by Eirlys