题目描述
传送门
题目大意: 有n个小朋友坐成一圈,每人有ai个糖果。每人只能给左右两人传递糖果。每人每次传递一个糖果代价为1。求使所有人获得均等糖果的最小代价。
题解
设
xi
表i给i+1传递的糖果的数量
那么我们可以得到n个方程
xn−x1=a¯−a1
x1−x2=a¯−a2
x2−x3=a¯−a3
⋯
xn−1−xn=a¯−an
那么对于方程做前缀和就能得到n个新的方程
xn−xi=∑ij=1a¯−aj
对于上面的方程进行变形,就能表示出
xi
xi=xn−∑ij=1a¯−aj
我们的目标就是要最小化
ans=∑ni=1|xi|=∑ni=1(xn−∑ij=1a¯−aj)
对于
xn
的取值,可以是不超过总和的任意值,显然所有的前缀和一定都在合法的范围之内。
那么我们只要让
xn
取到
xn−∑ij=1a¯−aj
中的中位数即可。
代码
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<cmath>
#define N 1000003
#define LL long long
using namespace std;
LL a[N],sum;
int n;
int main()
{
scanf("%d",&n);
for (int i=1;i<=n;i++) scanf("%lld",&a[i]),sum+=a[i];
sum/=n;
a[1]=sum-a[1];
for (int i=2;i<=n;i++){
int t=sum-a[i];
a[i]=a[i-1]+t;
}
sort(a+1,a+n+1);
LL t=a[n/2+1]; LL ans=0;
for (int i=1;i<=n;i++) ans+=abs(t-a[i]);
printf("%lld\n",ans);
}