P2512 糖果传递

有趣的思维题

[HAOI2008]糖果传递

题目描述

nn 个小朋友坐成一圈,每人有 aia_i 个糖果。每人只能给左右两人传递糖果。每人每次传递一个糖果代价为 11

输入格式

小朋友个数 nn,下面 nnaia_i

对于 100%100\% 的数据 n106n\le 10^6

输出格式

求使所有人获得均等糖果的最小代价。

题目分析

最终所有小朋友的糖果数量都是平均数,那么假设xix_iii号小朋友给i1i-1号小朋友糖果的个数,正表示给出,负代表被给。那么对于每一个小朋友,可以列出方程:

aixi+xi+1=avexi+1=xi+aveaia_i-x_i+x_{i+1}=ave\\ x_{i+1} = x_i+ave-a_i

带入每一个i可以得到:

{x2=x1+avea1x3=x2+avea2...xn=xn1+avean\left\{\begin{array}{c}     x_2 = x_1+ave-a_1 \\     x_3 = x_2+ave-a_2 \\ ...\\     x_n = x_{n-1}+ave-a_n \end{array}\right.

消元可得:

{x2=x1+avea1x3=x1+2avea1a2...xn=x1+(n1)avei=1n1ai\left\{\begin{array}{c}     x_2 = x_1+ave-a_1 \\     x_3 = x_1+2*ave-a_1-a_2 \\ ...\\     x_n = x_1+(n-1)*ave-\sum\limits_{i=1}^{n-1}a_i \end{array}\right.

题目要求的答案为 i=1nxi\sum\limits_{i=1}^{n}|x_i| 那么就转化为了
i=1nx1+(i1)avej=1iaj\sum\limits_{i=1}^n|x_1+(i-1)*ave-\sum\limits_{j=1}^ia_j|
那么问题就转化为了在数轴
x1x_1

iavej=1iaji*ave-\sum\limits_{j=1}^ia_j
这些点的距离之和,根据初中数学就能得知
x1x_1iavej=1iaji*ave-\sum\limits_{j=1}^ia_j
的中位数时答案最小,然后就做完啦。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
//
// Created by mrx on 2022/9/14.
//
#include <bits/stdc++.h>

using ll = long long;

int main() {
#ifdef LOCAL
freopen("in.txt", "r", stdin);
#endif
#ifndef LOCAL
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
std::cout.tie(nullptr);
#endif
int n;
while (std::cin >> n) {
std::vector<ll> c(n);
for (int i = 0; i < n; ++i) {
std::cin >> c[i];
if (i) c[i] += c[i - 1];
}
ll ave = c[n - 1] / n;
for (int i = 0; i < n; ++i) {
c[i] = (i + 1) * ave - c[i];
}

std::nth_element(c.begin(), c.begin() + n / 2, c.end());
ll x1 = c[n / 2];
ll ans = 0;
for (int i = 0; i < n; ++i) {
ans += std::abs(c[i] - x1);
}
std::cout << ans << '\n';
}
return 0;
}

P2512 糖果传递
https://mrxyan6.github.io/2022/09/15/P2512/
作者
mrx
发布于
2022年9月15日
许可协议