这道题本质上是一个数学题,先设xi为最优情况下第i个小朋友给第i-1个小朋友的糖果数(xi为负数代表是第i-1个小朋友给了第i个小朋友糖果),特殊情况:当i为1时,默认i-1=n,也就是x1表示第1个小朋友给第n个小朋友的糖果数。那我们的结果就是所有xi的绝对值的和了(传递糖果的个数即为最终代价),题目中已经给出每个小朋友一开始所拥有的糖果数ai,设每个小朋友最终取得的糖果数为mid,那么第i个小朋友最终的糖果数mid取决于一开始所具有的糖果数ai和他给第第i-1个小朋友的糖果数xi以及第i+1个小朋友给他的糖果数xi+1,也就是mid=ai-xi+x(i+1),化简得x(i+1)-xi=mid-ai,由这个式子可得
(1) x2-x1=mid-a1
(2) x3-x2=mid-a2
……
(n-1) xn-x(n-1)=mid-a(n-1)
对上述式子进行合并整理得
(1)+(2)得x3-x1=2*mid-(a2+a1)
(1)+(2)+(3)得x4-x1=3*mid-(a3+a2+a1)
……
(1)+(2)+……+(n-1)得xn-x1=(n-1)*mid-(a(n-1)+a(n-2)+……+a1)
对合并后的式子进行移项得:
x2=x1-(a1-mid)
x3=x1-((a2+a1)-2*mid)
x4=x1-((a3+a2+a1)-3*mid)
……
xn=x1-((a(n-1)+……+a2+a1)-(n-1)*mid)
又因为x1=x1-0
我们最终结果是xi的绝对值的和,看到上面移项后的式子容易想到距离公式,从而我们的结果就是一个点到0,(a1-mid),((a2+a1)-2*mid),……,((a(n-1)+……+a2+a1)-(n-1)*mid)这些点的距离和的最小值,这我们就可以转化为货仓选址问题了,直接取一个中位数进行计算即可,下面是代码:
#include<cstdio>
#include<iostream>
#include<cstring>
#include<vector>
#include<algorithm>
#include<map>
#include<cmath>
#include<queue>
using namespace std;
const int N=1000003;
long long a[N],s[N];
int main()
{
int n;
cin>>n;
for(int i=1;i<=n;i++)
{
scanf("%lld",&a[i]);
s[i]=s[i-1]+a[i];
}
long long mid=s[n]/n;
for(int i=1;i<=n;i++)
s[i]-=i*mid;
sort(s,s+n);
long long ans=0;
for(int i=0;i<n;i++)
ans+=abs(s[i]-s[n/2]);
printf("%lld",ans);
return 0;
}