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