bzoj 1045[HAOI2008] 糖果传递
1045: [HAOI2008] 糖果传递
Time Limit: 10 Sec Memory Limit: 162 MBDescription
有n个小朋友坐成一圈,每人有ai个糖果。每人只能给左右两人传递糖果。每人每次传递一个糖果代价为1。
Input
第一行一个正整数nn<=1'000'000,表示小朋友的个数.
接下来n行,每行一个整数ai,表示第i个小朋友得到的糖果的颗数.
Output
求使所有人获得均等糖果的最小代价。
Sample Input
4
1
2
5
4
1
2
5
4
Sample Output
4
设 x[i] 表示第i个人给第 i + 1 x[i]个糖果, (x[i] 可以为负)
所以$$ans = \sum\limits_{i = 1} ^n|x[i]|$$
又因为 avg = a[i] + x[i + 1] - x[i]
令 $sum[i] = \sum\limits_{i = 1}^n a[i]$
稍加转化
$$ans = \sum\limits_{i = 1}^n |x[i] + avg * i - sum[i]|$$
就是在数轴选一点是所有点到点的距离最大
1 #include <iostream> 2 #include <cstdio> 3 #include <algorithm> 4 #include <cstring> 5 #define LL long long 6 7 using namespace std; 8 9 const int MAXN = 1e6 + 10; 10 LL num[MAXN]; 11 int N; 12 LL sum[MAXN]; 13 LL C[MAXN]; 14 LL ans = 0; 15 inline LL read() 16 { 17 LL x = 0, w = 1; char ch = 0; 18 while(ch < '0' || ch > '9') { 19 if(ch == '-') { 20 w = -1; 21 } 22 ch = getchar(); 23 } 24 while(ch >= '0' && ch <= '9') { 25 x = x * 10 + ch - '0'; 26 ch = getchar(); 27 } 28 return x * w; 29 } 30 31 int main() 32 { 33 N = read(); 34 for(int i = 1; i <= N; i++) { 35 num[i] = read(); 36 sum[i] = sum[i - 1] + num[i]; 37 } 38 LL avg = sum[N] / N; 39 for(int i = 1; i <= N; i++) { 40 C[i] = sum[i] - avg * i; 41 } 42 sort(C, C + N); 43 for(int i = 0; i < N; i++) { 44 ans += abs(C[N / 2] - C[i]); 45 } 46 printf("%lld\n", ans); 47 return 0; 48 } 49 50 51 /* 52 53 4 54 1 55 2 56 5 57 4 58 59 */