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

好像Chrome支持MathJax有点问题。。Microsoft Edge一点事没有。。
因为一个一个小朋友传递,所以只用考虑两相邻两个小朋友间的关系。
xi 表示小朋友 i1 i 的糖果数,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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值