BZOJ-1045-[HAOI2008] 糖果傳遞(中位數原理)
阿新 • • 發佈:2017-10-23
event esc 原理 its 表示 style sed src 推出
1
2
5
4
Description
有n個小朋友坐成一圈,每人有ai個糖果。每人只能給左右兩人傳遞糖果。每人每次傳遞一個糖果代價為1。
Input
第一行一個正整數nn<=1‘000‘000,表示小朋友的個數. 接下來n行,每行一個整數ai,表示第i個小朋友得到的糖果的顆數.Output
求使所有人獲得均等糖果的最小代價。
Sample Input
41
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];View Code8 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] 糖果傳遞(中位數原理)