题目大意
有n个小朋友坐成一圈,每人有a_i颗糖果。
每人只能给左右两人传递糖果。
每人每次传递一颗糖果的代价为1。
求使所有人获得均等糖果的最小代价。
对于100%的数据,n<=10^6。
题目分析
有一..难。不要着急。
我搞明白了!
设x[i]表示i+1向i传的糖果数,x[n]表示1向n传的糖果数
a[1]+x[1]−x[n]=
a[2]+x[2]−x[1]=
a[3]+x[3]−x[2]=
⋯⋯⋯⋯
a[n−1]+x[n−1]−x[n−2]=把式子变形:
x[1]=
−a[1]+x[n]
x[2]=−a[2]+x[1]=2∗
−a[2]−a[1]+x[n]
x[3]=−a[3]+x[2]=3∗
−a[3]−a[2]−a[1]+x[n]
⋯⋯⋯⋯
x[n−1]=−a[n−1]+x[n−2]=(n−1)∗
−
a[i]+x[n]
x[n]=n∗−
a[i]+x[n]=0+x[n]
设s[i]=
a[j]−i∗
,则:
ans=∑∣x[i]∣=∑∣s[i]−x[n] ∣
所以当x[n]为{s[1],s[2],...,s[n]}的中位数时答案最小
以上摘自:https://www.cnblogs.com/CtrlCV/p/5626194.html 蒟蒻终于看懂了/哭/!!!
看懂了吗???如果你晕了,估计是卡在s[i]那了吧。反正我刚开始是(我也太弱了吧)。
那我添油加醋(貌似是个贬义词??)说点:(红色的是新加的辅助理解)
设s[i]=
a[j]−i∗
:
x[1]=
−a[1]+x[n]=x[n]-s[1]
x[2]=−a[2]+x[1]=2∗−a[2]−a[1]+x[n]=x[n]-s[2]
x[3]=−a[3]+x[2]=3∗
−a[3]−a[2]−a[1]+x[n]=x[n]-s[3]
⋯⋯⋯⋯
x[n−1]=−a[n−1]+x[n−2]=(n−1)∗
−
a[i]+x[n]=x[n]-s[n-1]
x[n]=n∗−
a[i]+x[n]=0+x[n]=x[n]-s[n]
(话说s[n]等于0这个不用说吧)
ans=∑∣x[i]∣=∑∣x[n]-s[i] ∣=∑∣s[i]−x[n] ∣
然后最后一句:所以当x[n]为{s[1],s[2],...,s[n]}的中位数时答案最小
这个应该可以证明ba,但是我已经强调我蒟了(强行甩锅),可以百度一下??
代码
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
long long ave,x=0,ans=0;
long long a[1000010],s[1000010];
int main()
{
int n; scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%lld",&a[i]);//每个人的初始糖果数
ave+=a[i];//平均数ave
}
ave/=n; a[n+1]=a[1];
for(int i=1;i<=n;i++)
{
x+=a[i];
s[i]=x-i*ave;
}
sort(s+1,s+1+n);
long long mid=s[n/2+1];//中位数
for(int i=1;i<=n;i++) ans+=abs(s[i]-mid);
printf("%lld",ans);
return 0;
}
记得最爱你的long long