[BZOJ1045] [HAOI2008] 糖果传递 (贪心)
Description
有n个小朋友坐成一圈,每人有ai个糖果。每人只能给左右两人传递糖果。每人每次传递一个糖果代价为1。
Input
第一行一个正整数n<=1000000,表示小朋友的个数.接下来n行,每行一个整数ai,表示第i个小朋友得到的
糖果的颗数.
Output
求使所有人获得均等糖果的最小代价。
Sample Input
1
2
5
4
Sample Output
HINT
Source
Solution
设$x[i]$表示$i+1$向$i$传的糖果数,$x[n]$表示$1$向$n$传的糖果数
$a[1]+x[1]-x[n]=\overline a$
$a[2]+x[2]-x[1]=\overline a$
$a[3]+x[3]-x[2]=\overline a$
$\cdots \cdots$
$a[n-1]+x[n-1]-x[n-2]=\overline a$
$a[n]+x[n]-x[n-1]=\overline a$(其实这个式子没用)
把式子变形:
$x[1]=\overline a-a[1]+x[n]$
$x[2]=\overline a-a[2]+x[1]=2*\overline a-a[2]-a[1]+x[n]$
$x[3]=\overline a-a[3]+x[2]=3*\overline a-a[3]-a[2]-a[1]+x[n]$
$\cdots \cdots$
$x[n-1]=\overline a-a[n-1]+x[n-2]=(n-1)*\overline a-\sum_{i=1}^{n-1}a[i]+x[n]$
$x[n]=n*\overline a-\sum_{i=1}^{n}a[i]+x[n]=0+x[n]$
设$\displaystyle s[i]=\sum_{j=1}^{i}a[j]-i*\overline a$,则:
$\displaystyle ans=\sum\mid x[i]\mid\ =\sum\mid s[i]-x[n]\ \mid$
所以当$x[n]$为$\big\{s[1], s[2], ..., s[n]\big\}$的中位数时答案最小
题面数据范围是在搞笑的,糖果数在$int$范围,答案在$long\ long$范围,剩下的就没什么难度了
1 #include <bits/stdc++.h> 2 using namespace std; 3 long long a[1000005], s[1000005]; 4 int main() 5 { 6 int n; 7 long long ave = 0, ans = 0; 8 scanf("%d", &n); 9 for(int i = 1; i <= n; ++i) 10 scanf("%lld", a + i); 11 for(int i = 1; i <= n; ++i) 12 ave += a[i]; 13 ave /= n; 14 for(int i = 1; i <= n; ++i) 15 s[i] = s[i - 1] + a[i] - ave; 16 sort(s + 1, s + n + 1); 17 for(int i = 1; i < n / 2 + 1; ++i) 18 ans += s[n / 2 + 1] - s[i]; 19 for(int i = n / 2 + 1; i <= n; ++i) 20 ans += s[i] - s[n / 2 + 1]; 21 printf("%lld\n", ans); 22 return 0; 23 }
接下来是有爱的双倍经验时间:$BZOJ3293$