一、题目
二、解法
设
x
i
x_i
xi为
i
i
i号给
i
−
1
i-1
i−1号
x
i
x_i
xi颗糖果(如果为负则方向相反),让后我们可以列出下面的式子:
a
1
−
x
1
+
x
2
=
a
v
e
a_1-x_1+x_2=ave
a1−x1+x2=ave
…
…
\dots \dots
……
a
i
−
x
i
+
x
i
+
1
=
a
v
e
a_i-x_i+x_{i+1}=ave
ai−xi+xi+1=ave
发现有
n
n
n个方程,
n
n
n个未知数,可以解出关系式(定义
c
[
i
]
=
∑
j
=
1
i
a
[
j
]
−
a
v
e
c[i]=\sum_{j=1}^{i} a[j]-ave
c[i]=∑j=1ia[j]−ave):
x
i
=
x
1
−
c
[
i
]
x_i=x_1-c[i]
xi=x1−c[i]
我们的答案就是
∣
x
1
∣
+
∣
x
1
−
c
[
1
]
∣
+
.
.
.
+
∣
x
1
−
c
[
n
−
1
]
∣
|x_1|+|x_1-c[1]|+...+|x_1-c[n-1]|
∣x1∣+∣x1−c[1]∣+...+∣x1−c[n−1]∣
可以发现这就是个小学的邮局问题,取
c
c
c的中位数即可。(说中位数可能有点不严谨,详细操作看代码吧)
#include <cstdio>
#include <algorithm>
using namespace std;
#define int long long
const int MAXN = 1000005;
int read()
{
int x=0,flag=1;char c;
while((c=getchar())<'0' || c>'9') if(c=='-') flag=-1;
while(c>='0' && c<='9') x=(x<<3)+(x<<1)+(c^48),c=getchar();
return x*flag;
}
int n,ave,ans,a[MAXN],s[MAXN];
int _abs(int x)
{
return x>0?x:-x;
}
signed main()
{
n=read();
for(int i=1;i<=n;i++)
{
a[i]=read();
ave+=a[i];
}
ave/=n;
for(int i=1;i<n;i++)
s[i]=s[i-1]+a[i]-ave;
sort(s+1,s+n);
int x1=s[(n+1)/2],val=_abs(x1);
for(int i=1;i<n;i++)
ans+=_abs(x1-s[i]);
n--;
if(n%2==0) val=min(_abs(s[n/2]),_abs(s[n/2+1]));
printf("%lld\n",ans+val);
}