bzoj 1045[HAOI2008] 糖果传递

1045: [HAOI2008] 糖果传递

Time Limit: 10 Sec  Memory Limit: 162 MB

Description

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

Input

第一行一个正整数nn<=1'000'000,表示小朋友的个数.
接下来n行,每行一个整数ai,表示第i个小朋友得到的糖果的颗数.

Output

求使所有人获得均等糖果的最小代价。

Sample Input

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 */
View Code

 

posted @ 2018-03-24 15:21  大财主  阅读(105)  评论(0编辑  收藏  举报