BZOJ 1045 HAOI 2008 糖果传递 数学推导

来源:互联网 发布:学数据库需要学编程吗 编辑:程序博客网 时间:2024/05/20 14:41

好像Chrome支持MathJax有点问题。。Microsoft Edge一点事没有。。
因为一个一个小朋友传递,所以只用考虑两相邻两个小朋友间的关系。
xi表示小朋友i1i的糖果数,v=1nai,那么显然有:

ans=|xi|

而且对于每个小朋友有:
v=ai+xixi+1

因此
xi+1=xi+aiv

因此,{xi}之间存在一个关系,使得某个xi定下来了以后,其他xj都确定了,因而答案ans也确定了。
假设我们固定x1,那么对于其他数字,如
x2x3=x1+a1v=x2+a2v=x1+a1v+a2v

我们设c0=0,ci=ci1ai+v,那么有
xi=x1ci

答案有
ans=|x1c0|+|x1c1|+|x1c2|++|x1cn1|

发现这个式子表示的就是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

0 0
原创粉丝点击