好像Chrome支持MathJax有点问题。。Microsoft Edge一点事没有。。
因为一个一个小朋友传递,所以只用考虑两相邻两个小朋友间的关系。
令
xi
表示小朋友
i−1
给
i
的糖果数,
ans=∑|xi|
而且对于每个小朋友有:
v=ai+xi−xi+1
因此
xi+1=xi+ai−v
因此, {xi} 之间存在一个关系,使得某个 xi 定下来了以后,其他 xj 都确定了,因而答案 ans 也确定了。
假设我们固定 x1 ,那么对于其他数字,如
x2x3=x1+a1−v=x2+a2−v=x1+a1−v+a2−v⋯
我们设 c0=0,ci=ci−1−ai+v ,那么有
xi=x1−ci
答案有
ans=|x1−c0|+|x1−c1|+|x1−c2|+⋯+|x1−cn−1|
发现这个式子表示的就是 x1 在数轴上与 ci 的距离和,要使距离和最小,就要使 x1=ci 的中位数,问题就解决了。
发的时候用I64d跪了。。。
#include <cstdio>
#include <cstdlib>
#include <algorithm>
using namespace std;
typedef long long ll;
#define FOR(i,j,k) for(i=j;i<=k;i++)
const int N = 10000005;
ll read() {
ll s = 0, f = 1; char ch = getchar();
for (; ch < '0' || ch > '9'; ch = getchar()) if (ch == '-') f = -1;
for (; '0' <= ch && ch <= '9'; ch = getchar()) s = s * 10 + ch - '0';
return s * f;
}
int main() {
static int a[N], s[N];
ll n = read(), i, x, tot = 0, avg, mid, ans;
s[0] = 0;
FOR(i,1,n) a[i] = read(), tot += a[i];
avg = tot / n;
FOR(i,1,n-1) s[i] = s[i - 1] + a[i] - avg;
sort(s + 1, s + n);
mid = s[n / 2];
ans = abs(mid);
FOR(i,1,n-1) ans += abs(s[i] - mid);
printf("%lld\n", ans);
return 0;
}
1045: [HAOI2008] 糖果传递
Time Limit: 10 Sec Memory Limit: 162 MB
Submit: 3047 Solved: 1378
Description
有n个小朋友坐成一圈,每人有ai个糖果。每人只能给左右两人传递糖果。每人每次传递一个糖果代价为1。
Input
小朋友个数n 下面n行 ai
Output
求使所有人获得均等糖果的最小代价。
Sample Input
4
1
2
5
4
Sample Output
4
HINT
100% n<=987654321