1045: [HAOI2008] 糖果传递 - BZOJ

Description

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

小朋友个数n 下面n行 ai
Output

求使所有人获得均等糖果的最小代价。
Sample Input
4
1
2
5
4

Sample Output
4
数据规模
30% n<=1000
100% n<=1000000

 

说难又不难,我对数学题没什么感觉啊

首先,均分纸牌都做过吧(什么,没做过!?百度NOIP2002均分纸牌)

这个只是环形而已,为了把它变成环形,我们要知道a1给了an多少

不妨设a1给an的糖果数为k

那我们的答案就是ans=k+|a1-k-average|+|a1+a2-k-2*average|+|a1+a2+a3-k-3*average|+......+|a1+a2+a3+......+a(n-1)-k-(n-1)*average|

前面的k可以看成|0-k|

所以我求的就是|0-k|+|a1-k-average|+|a1+a2-k-2*average|+|a1+a2+a3-k-3*average|+......+|a1+a2+a3+......+a(n-1)-k-(n-1)*average|的最小值

这个就是一道经典的奥赛题了,k取中位数时最小,排个序就行了

 1 const

 2     maxn=1000010;

 3 var

 4     b:array[0..maxn]of int64;

 5     a:array[0..maxn]of longint;

 6     n:longint;

 7     x,k,ans:int64;

 8 

 9 procedure init;

10 var

11     i:longint;

12 begin

13     read(n);

14     for i:=1 to n do

15       begin

16         read(a[i]);

17         inc(x,a[i]);

18       end;

19     x:=x div n;

20 end;

21 

22 procedure sort(l,r:longint);

23 var

24     i,j:longint;

25     t,y:int64;

26 begin

27     i:=l;

28     j:=r;

29     y:=b[(l+r)>>1];

30     repeat

31       while b[i]<y do

32         inc(i);

33       while b[j]>y do

34         dec(j);

35       if i<=j then

36       begin

37         t:=b[i];

38         b[i]:=b[j];

39         b[j]:=t;

40         inc(i);

41         dec(j);

42       end;

43     until i>j;

44     if i<r then sort(i,r);

45     if j>l then sort(l,j);

46 end;

47 

48 procedure work;

49 var

50     i:longint;

51 begin

52     b[1]:=0;

53     for i:=2 to n do

54       b[i]:=b[i-1]+a[i-1]-x;

55     sort(1,n);

56     k:=b[(n+1)>>1];

57     for i:=1 to n do

58       inc(ans,abs(b[i]-k));

59     write(ans);

60 end;

61 

62 begin

63     init;

64     work;

65 end.
View Code

 

你可能感兴趣的:(2008)