时空限制 1000ms / 128MB
题目描述
有n个小朋友坐成一圈,每人有ai个糖果。每人只能给左右两人传递糖果。每人每次传递一个糖果代价为1
输入格式:
小朋友个数n 下面n行 ai
输出格式:
求使所有人获得均等糖果的最小代价。
说明
对于100%的数据 n ≤ 1 0 6 n≤10^6 n≤106
题目分析
学算法学傻了,一眼扫过去 “woc费用流水题”
然后开心的五分钟打完费用流,再然后。。就没有然后了
设1给n k个
1
−
>
n
:
k
1->n:k
1−>n:k
2
−
>
1
:
a
‾
−
(
a
1
−
k
)
=
a
‾
−
a
1
+
k
2->1:\overline{a}-(a_1-k)=\overline{a}-a_1+k
2−>1:a−(a1−k)=a−a1+k
3
−
>
2
:
a
‾
−
(
a
2
−
(
a
‾
−
a
1
+
k
)
)
=
a
‾
∗
2
−
a
1
−
a
2
+
k
3->2:\overline{a}-(a_2-(\overline{a}-a_1+k))=\overline{a}*2-a_1-a_2+k
3−>2:a−(a2−(a−a1+k))=a∗2−a1−a2+k
⋯
\cdots
⋯
n
−
>
n
−
1
:
∑
i
=
1
n
−
1
(
a
‾
−
a
i
)
+
k
n->n-1:\sum_{i=1}^{n-1}(\overline{a}-a_i)+k
n−>n−1:∑i=1n−1(a−ai)+k
记每个
∑
i
=
1
j
−
1
a
‾
−
a
i
\sum_{i=1}^{j-1}{\overline{a}-a_i}
∑i=1j−1a−ai记为
c
j
c_j
cj
那么有
∑
i
=
1
n
∣
c
i
+
k
∣
\sum_{i=1}^n|c_i+k|
∑i=1n∣ci+k∣ ,由小学奥数知k为c数组的中位数的相反数
#include<iostream>
#include<cstdio>
#include<cmath>
#include<queue>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long lt;
int read()
{
int f=1,x=0;
char ss=getchar();
while(ss<'0'||ss>'9'){if(ss=='-')f=-1;ss=getchar();}
while(ss>='0'&&ss<='9'){x=x*10+ss-'0';ss=getchar();}
return f*x;
}
const int maxn=1000010;
int n;
lt a[maxn],b[maxn],c[maxn];
lt sum,avg,ans;
int main()
{
n=read();
for(int i=1;i<=n;++i)
a[i]=read(),sum+=a[i];
avg=sum/n;
for(int i=2;i<=n;++i)
c[i]=c[i-1]+avg-a[i-1];
sort(c+1,c+1+n);
lt k=-c[(n+1)/2];
for(int i=1;i<=n;++i) ans+=abs(c[i]+k);
printf("%lld",ans);
return 0;
}