[BZOJ1045][HAOI2008]糖果传递 数学
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1045
我们假设每一个小朋友的代价为$x[i]$,每一次都从前面一个小朋友那里拿,这种贪心跟纸牌均摊很像,想一想很容易理解。
设最后每个小朋友能得到$ave$个糖果,所以有$a[i]+x[i]-x[i+1]=ave$。
写出每一个形如这样的式子,可以消元得到$x[n]=x[1]+(n-1)*ave-sum[n-1]$。
我们令$c[i]=(i-1)*ave-sum[i-1]$,则我们最后所求为$Ans=\{\sum_{i=1}^n|x[1]-c[i]|\}_{min}$。
把$x[1]$和$c[i]$看成数轴上的点,可以证明当$x[1]$为$c[i]$的中位数时,取得$Ans$值。
1 #include<cstdio> 2 #include<cstring> 3 #include<cmath> 4 #include<algorithm> 5 using namespace std; 6 typedef long long ll; 7 int inline readint(){ 8 int Num;char ch; 9 while((ch=getchar())<'0'||ch>'9') ;Num=ch-'0'; 10 while((ch=getchar())>='0'&&ch<='9') Num=Num*10+ch-'0'; 11 return Num; 12 } 13 int N; 14 ll a[1000010],b[1000010],ave; 15 int main(){ 16 N=readint(); 17 ll sum=0; 18 for(int i=1;i<=N;i++){ 19 a[i]=readint(); 20 sum+=a[i]; 21 } 22 ave=sum/N; 23 sum=0; 24 for(int i=1;i<=N;i++){ 25 b[i]=ave*(i-1)-sum; 26 sum+=a[i]; 27 } 28 sort(b+1,b+1+N); 29 int mid=N+1>>1; 30 ll ans=0; 31 for(int i=1;i<=N;i++) ans+=abs(b[mid]-b[i]); 32 printf("%lld\n",ans); 33 return 0; 34 }