[HAOI2008]糖果傳遞
阿新 • • 發佈:2018-10-31
code getc element 題解 輸出 前綴和 clas print 增加 最小
題目描述
有n個小朋友坐成一圈,每人有ai個糖果。每人只能給左右兩人傳遞糖果。每人每次傳遞一個糖果代價為1。
輸入輸出格式
輸入格式:
小朋友個數n 下面n行 ai
輸出格式:
求使所有人獲得均等糖果的最小代價。
輸入輸出樣例
輸入樣例#1:
4
1
2
5
4
輸出樣例#1:
4
說明
對於100%的數據 \(n<=10^6\)
題解
環形均分紙牌
先考慮線性的均分紙牌是怎麽做的
先求出平均值ave
然後將每堆的牌數-ave
表示需要增加/扔出多少張紙牌
然後求一個前綴和Sum
把n個前綴和加起來就是答案了
那麽環形的均分紙牌也是類似
只是我們要考慮破環為鏈
那麽我們就是要求\(\sum_{i=1}^{n}{Sum[i]-Sum[t]}\)
這個\(t\)顯然就是所有\(Sum[]\)的中位數所對應的位置
代碼
#include<cstdio> #include<algorithm> # define LL long long const int M = 1000005 ; using namespace std ; inline LL read() { char c = getchar() ; LL x = 0 , w = 1 ; while(c>'9'||c<'0') { if(c=='-') w = -1 ; c = getchar() ; } while(c>='0'&&c<='9') { x = x*10+c-'0' ; c = getchar() ; } return x*w ; } int n , mid ; LL v[M] , ave , sum[M] , Ans ; int main() { n = read() ; mid = (n + 1) >> 1 ; for(int i = 1 ; i <= n ; i ++) v[i] = read() , ave += v[i] ; ave /= n ; for(int i = 1 ; i <= n ; i ++) v[i] -= ave ; for(int i = 1 ; i <= n ; i ++) sum[i] = sum[i - 1] + v[i] ; nth_element(sum + 1 , sum + mid , sum + n + 1) ; for(int i = 1 ; i <= n ; i ++) Ans += abs(sum[i] - sum[mid]) ; printf("%lld\n",Ans) ; return 0 ; }
[HAOI2008]糖果傳遞