题面传送门
又是数学题。
设
a
i
a_i
ai 为本来钱数,
b
i
b_i
bi 为给后一个人多少钱,
m
m
m 为平均分的钱数。
则:
a
1
−
b
1
+
b
2
=
m
a_1-b_1+b_2=m
a1−b1+b2=m
a
1
−
b
1
+
b
2
=
m
a_1-b_1+b_2=m
a1−b1+b2=m
b
2
=
b
1
−
(
a
1
−
m
)
b_2=b_1-(a_1-m)
b2=b1−(a1−m)
a
2
−
b
2
+
b
3
=
m
a_2-b_2+b_3=m
a2−b2+b3=m
b
3
=
2
m
−
a
2
+
b
1
−
a
1
b_3=2m-a_2+b_1-a_1
b3=2m−a2+b1−a1
所以 可得
b
3
=
b
1
−
(
a
1
−
m
)
−
(
a
2
−
m
)
b_3=b_1-(a_1-m)-(a_2-m)
b3=b1−(a1−m)−(a2−m)
以此类推,
b
i
=
b
1
−
∑
j
=
1
i
−
1
(
a
j
−
m
)
b_i=b_1-\sum\limits_{j=1}^{i-1}{(a_j-m)}
bi=b1−j=1∑i−1(aj−m)
所以原题变为求
∑
i
=
1
n
∣
b
1
−
∑
j
=
1
i
−
1
(
a
j
−
m
)
∣
\sum\limits_{i=1}^{n}{\left|b_1-\sum\limits_{j=1}^{i-1}{(a_j-m)}\right|}
i=1∑n∣∣∣∣∣b1−j=1∑i−1(aj−m)∣∣∣∣∣第二重循环可以用前缀和优化,那么只要让
b
1
b_1
b1 最小就 行了。找中点呗!
代码实现:
#include<cstdio>
#include<cmath>
#include<algorithm>
#define abs(x) ((x)>0?(x):-(x))
using namespace std;
int m,n;
long long ans,tot,pus,now,q[1000039],a[1000039];
inline void read(long long &x){
char s=getchar();x=0;
while(s<48||s>57) s=getchar();
while(s>=48&&s<=57) x=(x<<3)+(x<<1)+(s^48),s=getchar();
}
int main(){
register int i;
scanf("%d",&n);
for(i=1;i<=n;i++)read(a[i]),ans+=a[i];
m=ans/n;
for(i=1;i<=n;i++) a[i]-=m,q[i]=q[i-1]+a[i];
sort(q+1,q+n+1);
now=q[(int)ceil(n*1.0/2)];
for(i=1;i<=n;i++) tot+=abs(q[i]-now);
printf("%lld",tot);
return 0;
}