BZOJ-1045-[HAOI2008] 糖果传递(中位数原理)

Posted I__am

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ-1045-[HAOI2008] 糖果传递(中位数原理)相关的知识,希望对你有一定的参考价值。

Description

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

Input

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

Output

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

Sample Input

4
1
2
5
4

Sample Output

4
 

题解

这道题对于最终小朋友手中的糖的数量我们是可以算出来的,我们用ave来表示

我们假设Gi表示第i个人给第i-1个人糖的数量,G1表示第1个人给第n个人

那么最后答案就是|G1|+|G2|+···+|Gn|

那么到最后

第一个人的糖就是A1-G1+G2=ave

第二个人的糖就是A2-G2+G3=ave

······

第n个人的糖就是An-Gn+G1=ave

这里我们假设Ci=Ci-1+Ai-ave

所以通过第一个人的糖,我们可以推出G2=G1-C1

通过第二个人,可以推出G3=G1-C2

······

第n个人,可以推出Gn=G1-Cn-1

所以最后答案就变成了|G1|+|G1-C1|+|G1-C2|+···+|G1-Cn-1|

对于求最后答案,问题就变成了给你坐标轴上的n个点,要你找到一个点,使得这个点到所有的点的距离之和最小

而这个点的坐标就是坐标轴上点的中位数

技术分享
 1 #include<bits/stdc++.h>
 2 #define N 1000005
 3 #define ll long long
 4 using namespace std;
 5 int n,ave;
 6 ll sum,ans;
 7 int a[N],c[N];
 8 int main(){
 9     scanf("%d",&n);
10     for (int i=1;i<=n;i++){
11         scanf("%d",&a[i]);
12         sum+=a[i];
13     }
14     ave=sum/n;
15     for (int i=2;i<=n;i++)
16         c[i]=c[i-1]+a[i]-ave;
17     sort(c+1,c+1+n);
18     int mid=c[(n>>1)+1];
19     for (int i=1;i<=n;i++)
20         ans+=abs(mid-c[i]);
21     printf("%lld\n",ans);
22     return 0;
23 }
View Code

 

以上是关于BZOJ-1045-[HAOI2008] 糖果传递(中位数原理)的主要内容,如果未能解决你的问题,请参考以下文章

bzoj1045: [HAOI2008] 糖果传递(数论)

bzoj1045[HAOI2008] 糖果传递

[bzoj1045] [HAOI2008] 糖果传递

[BZOJ1045] [HAOI2008] 糖果传递 (贪心)

贪心bzoj1045: [HAOI2008] 糖果传递

bzoj 1045 [HAOI2008] 糖果传递 —— 贪心