Description:
有
n
n
个小朋友坐成一圈,每人有个糖果。每人只能给左右两人传递糖果。每人每次传递一个糖果代价为
1
1
。求代价最小。
Solution:
设第个人传给第
i
i
个人个,那么
xi−xi+1+ai=v
x
i
−
x
i
+
1
+
a
i
=
v
那么我们得出
xi+1=xi+ai−v
x
i
+
1
=
x
i
+
a
i
−
v
设
ci=v−ai
c
i
=
v
−
a
i
那么
x2=x1−c1
x
2
=
x
1
−
c
1
x3=x2−c2=x1−c1−c2
x
3
=
x
2
−
c
2
=
x
1
−
c
1
−
c
2
对
ci
c
i
做前缀和
得出
xi=x1−si−1
x
i
=
x
1
−
s
i
−
1
那么答案是
∑ni=1|si−1−x1|
∑
i
=
1
n
|
s
i
−
1
−
x
1
|
自然
x1
x
1
取
s
s
<script type="math/tex" id="MathJax-Element-16">s</script>的中位数时答案最小。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e6 + 5;
int n;
ll v, ans;
ll a[maxn], s[maxn];
int read() {
int x = 0, f = 1;
char c = getchar();
while(!isdigit(c)) {
if(c == '-') {
f = -1;
}
c = getchar();
}
while(isdigit(c)) {
x = x * 10 + c - '0';
c = getchar();
}
return x * f;
}
int main() {
n = read();
for(int i = 1; i <= n; ++i) {
a[i] = read();
v += a[i];
}
v /= n;
for(int i = 2; i <= n; ++i) {
s[i] = s[i - 1] + a[i] - v;
}
sort(s + 1, s + n + 1);
ll t = s[(n + 1) / 2];
for(int i = 1; i <= n; ++i) {
ans += abs(s[i] - t);
}
printf("%lld\n", ans);
return 0;
}