题目链接:#10010. 「一本通 1.1 练习 6」糖果传递 - 题目 - LibreOJ (loj.ac)
思路:
设 xi 表示第 i 个人向第 i-1 个人传递 xi 颗糖果
x1 x2 x3 ... xn x1
an -> a1 -> a2 -> a3 -> ... -> an-1 -> an -> a1
第i个人加上前一个人传递给自己的再减去自己传递给下一个人的糖果为平均值
a1 + x1 - x2 = ave
a2 + x2 - x3 = ave
a3 + x3 - x4 = ave
...
得到式子
an + xn - xn-1 = ave
x1 = x1 + c1 = 0
x2 = a1 - ave + x1
x3 = a2 - ave + x2 = (a1 - ave) + (a2 - ave) + x1
...
xn = (a1 - ave) + (a2 - ave) + ... + (an-1 - ave) + x1
i == 1 c[i] = 0
i >= 2 c[i] = c[i - 1] + a[i - 1] - ave
ans = min(abs(x1) + abs(x2) + ... + abs(xn))
= min(abs(x1 + c1) + abs(x2 + c2) + ... + abs(xn + cn))
= min(abs(c1 - (-x1)) + abs(c2 - (x2)) + ... + abs(cn - (-xn)))
自己也是看着b站视频一步步跟着推导公式,如果不理解的建议大家也去看下。博主为时吉科技,主页里搜索题目即可,最后输出答案还要学习一下货仓选址这道题,以便更好理解中位数在其中的作用。
AC代码
#include <map>
#include <set>
#include <stack>
#include <queue>
#include <cmath>
#include <vector>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define endl '\n'
#define ll long long
#define inf 0x3f3f3f3f
#define lowbit(x) x & (-x)
using namespace std;
const int N = 1e6 + 10;
int t, n, q, x, l, r, c[N], a[N];
ll sum, ave, ans;
int main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int i, j;
cin >> n;
for (i = 0; i < n; i ++) {
cin >> a[i];
sum += a[i];
}
ave = sum / n;
for (i = 1; i < n; i ++) {
c[i] = c[i - 1] + a[i - 1] - ave;
}
sort(c, c + n);
for (i = 0; i < n; i++) {
ans += abs(c[n / 2] - c[i]);
}
cout << ans << '\n';
return 0;
}