[HAOI2008] 糖果传递
考虑相似题目均分纸牌
当每个人没有做成一个圈,也就是考虑在一个序列上的转移,我们规定每个人只向他后面的人传递糖果,比如,第一第二两人持有的糖果数分别为\(A_1\) \(A_2\),我们要将糖果数均分为k,那么第一个人要向第二个人传递\(C_1=A_1-k\)个糖果,第二个人要向第三个人传递\(C_2=A_2+C_1-k\)个糖果
显然,这个做法是正确的,当我们的第一个人向第二个人传递\(C_1\)个糖果时,第一个人的糖果数等于k,我们只需要考虑从第二个人开始后面的人去均分糖果,同样,当我们第二个人转移后,我们只需要考虑第三个人之后,直到均分整个序列
重新思考环形时的解法
我们可以先断开一条边形成一个序列,假设现在有n个人围成一个环,我们设第i个人持有的糖果数为\(A_i\),均分后的糖果数为k
我们设$$C_i=C_{i-1}+A_i-k (i>1),C_1=C_n+A_1-k$$
即第i个人向第i+1个人转移的糖果数,将上式推为
\[C_1=C_n+A_1-k
\]
\[C_2=C_1+A_2-k=C_n+A_1+A_2-2k
\]
\[C_3=C_2+A_3-k=C_n+A_1+A_2+A_3-3k
\]
\[.
\]
\[.
\]
\[.
\]
\[C_n=C_{n-1}+A_1+A_2+...+A_{n-1}-nk
\]
我们发现,\(C_i\)的后几项格式相同,我们就可以设
\[P_i=\sum_{j=1}^{j<=i}A_j-i*k
\]
这时,我们就可以将上式改为
\[C_i=P_i+C_n
\]
最终答案就为
\[ans=\sum_{i=1}^{i<=n}|C_i|=\sum_{i=1}^{1<=n}|P_i+C_n|
\]
我们可以将上式理解为\(C_n\)到\(P_{1<=i<=n}\)的距离之和,很显然,\(C_n\)取C中的中位数就行
我们将C数组与P数组预处理出来,求出C的中位数,计算答案即可
using namespace std;
#define ll long long
#define MAXN 1000010
inline ll read(){
ll x=0,f=1;
char c=getchar();
while(c<'0'||c>'9'){
if(c=='-')f=-1;
c=getchar();
}
while(c>='0'&&c<='9'){
x=x*10+c-'0';
c=getchar();
}
return x*f;
}
ll a[MAXN],p[MAXN],c[MAXN];
ll n,k,s,ans;
pair <ll,ll> q[MAXN];
int main(){
n=read();
for(int i=1;i<=n;i++){
k+=a[i]=read();
}
k/=n;
for(int i=1;i<=n;i++){
c[i]=a[i]-k;
p[i]=p[i-1]+a[i]-k;
}
sort(p+1,p+1+n);
s=p[(n+1)/2];
for(int i=1;i<=n;i++){
ans+=abs(p[i]-s);
}
cout<<ans<<endl;
return 0;
}

浙公网安备 33010602011771号