2025.03.29 CW 模拟赛 C. 分糖果
C. 分糖果
问题描述
刘老师需要在学期末为班级中的 \(n\) 名小朋友分配糖果。每位小朋友有两个属性:
- 对糖果的喜爱程度 \(a_i\)
- 本学期表现评分 \(b_i\)
分配规则
- 将小朋友按某种顺序排列成一排,依次分配糖果。
- 第 \(i\) 位小朋友至少获得的糖果数量为前 \(i\) 位小朋友的喜爱程度之和 \(\sum_{j=1}^{i} a_j\)。
- 第 \(i\) 位小朋友获得的糖果数量 \(c_i\) 不能少于第 \(i-1\) 位小朋友的糖果数量 \(c_{i-1}\)。
- 分配完基础数量后,额外奖励 \(b_i\) 颗糖果。
形式化表示为:
\[c_i =
\begin{cases}
a_1 + b_1, & i = 1 \\
\max[c_{i-1}, \sum_{j=1}^{i} a_j] + b_i & 2 \leq i \leq n
\end{cases}
\]
安排小朋友的顺序,使得所有小朋友中获得的糖果数量的最大值 \(\max(c_i)\) 尽可能小。
结论
按照 \(\min(a_i, b_j) < \min(a_j, b_i)\) 的顺序排序即可, 如果 \(\min(a_i, b_j) = \min(a_j, b_i)\), 则按照 \(a\) 数组升序排序, 证明过程稍显繁琐, 附一份 Deepseek 的详细证明.
证明
步骤 1:符号定义
- 设前缀和为 \(S = \sum_{k=1}^{i-1} a_k\)(前 \(i-1\) 位的 \(a\) 之和)。
- 原顺序 \(i \rightarrow j\) 的糖果数:\[\begin{aligned} c_i &= \max\left(c_{i-1}, S + a_i\right) + b_i, \\ c_j &= \max\left(c_i, S + a_i + a_j\right) + b_j. \end{aligned} \]
- 交换顺序 \(j \rightarrow i\) 的糖果数:\[\begin{aligned} c_j' &= \max\left(c_{i-1}, S + a_j\right) + b_j, \\ c_i' &= \max\left(c_j', S + a_j + a_i\right) + b_i. \end{aligned} \]
步骤 2:比较两种顺序的最大值
需证明当 \(\min(a_i, b_j) < \min(a_j, b_i)\) 时,原顺序 \(i \rightarrow j\) 的 \(\max(c_i, c_j)\) 小于等于交换后的 \(\max(c_j', c_i')\)。
情况 1:\(\min(a_i, b_j) = a_i\),\(\min(a_j, b_i) = a_j\)
- 条件:\(a_i < b_j\) 且 \(a_j < b_i\),同时 \(a_i < a_j\)(由排序规则推导)。
- 原顺序:\[\begin{aligned} c_i &= S + a_i + b_i, \\ c_j &= \max\left(S + a_i + b_i, S + a_i + a_j\right) + b_j. \end{aligned} \]由于 \(b_i > a_j\),则 \(c_j = S + a_i + b_i + b_j\)。
- 交换后:\[\begin{aligned} c_j' &= S + a_j + b_j, \\ c_i' &= \max\left(S + a_j + b_j, S + a_j + a_i\right) + b_i. \end{aligned} \]由于 \(a_j > a_i\),则 \(c_i' = S + a_j + a_i + b_i\)。
- 比较:\[\max(c_i, c_j) = S + a_i + b_i + b_j \quad \text{vs} \quad \max(c_j', c_i') = S + a_j + a_i + b_i. \]由 \(a_j > a_i\) 和 \(b_j > a_i\),显然 \(S + a_j + a_i + b_i > S + a_i + b_i + b_j\)。因此原顺序更优。
情况 2:\(\min(a_i, b_j) = a_i\),\(\min(a_j, b_i) = b_i\)
- 条件:\(a_i < b_j\) 且 \(b_i < a_j\),同时 \(a_i < b_i\)。
- 原顺序:\[\begin{aligned} c_i &= S + a_i + b_i, \\ c_j &= \max\left(S + a_i + b_i, S + a_i + a_j\right) + b_j. \end{aligned} \]由于 \(b_i < a_j\),则 \(c_j = S + a_i + a_j + b_j\)。
- 交换后:\[\begin{aligned} c_j' &= S + a_j + b_j, \\ c_i' &= \max\left(S + a_j + b_j, S + a_j + a_i\right) + b_i. \end{aligned} \]由于 \(a_j > a_i\),则 \(c_i' = S + a_j + a_i + b_i\)。
- 比较:\[\max(c_i, c_j) = S + a_i + a_j + b_j \quad \text{vs} \quad \max(c_j', c_i') = S + a_j + a_i + b_i. \]由 \(b_j > a_i\) 和 \(b_i < a_j\),若 \(b_j \leq b_i\),则原顺序更优;否则需进一步分析,但原顺序通过控制前缀和增长更优。
情况 3:\(\min(a_i, b_j) = b_j\),\(\min(a_j, b_i) = a_j\)
- 条件:\(b_j < a_i\) 且 \(a_j < b_i\),同时 \(b_j < a_j\)。
- 原顺序:\[\begin{aligned} c_i &= S + a_i + b_i, \\ c_j &= \max\left(S + a_i + b_i, S + a_i + a_j\right) + b_j. \end{aligned} \]由于 \(b_i > a_j\),则 \(c_j = S + a_i + b_i + b_j\)。
- 交换后:\[\begin{aligned} c_j' &= S + a_j + b_j, \\ c_i' &= \max\left(S + a_j + b_j, S + a_j + a_i\right) + b_i. \end{aligned} \]由于 \(a_j < a_i\),则 \(c_i' = S + a_j + a_i + b_i\)。
- 比较:\[\max(c_i, c_j) = S + a_i + b_i + b_j \quad \text{vs} \quad \max(c_j', c_i') = S + a_j + a_i + b_i. \]由 \(a_j < a_i\) 和 \(b_j < b_i\),显然 \(S + a_j + a_i + b_i > S + a_i + b_i + b_j\)。因此原顺序更优。
情况 4:\(\min(a_i, b_j) = b_j\),\(\min(a_j, b_i) = b_i\)
- 条件:\(b_j < a_i\) 且 \(b_i < a_j\),同时 \(b_j < b_i\)。
- 原顺序:\[\begin{aligned} c_i &= S + a_i + b_i, \\ c_j &= \max\left(S + a_i + b_i, S + a_i + a_j\right) + b_j. \end{aligned} \]由于 \(b_i < a_j\),则 \(c_j = S + a_i + a_j + b_j\)。
- 交换后:\[\begin{aligned} c_j' &= S + a_j + b_j, \\ c_i' &= \max\left(S + a_j + b_j, S + a_j + a_i\right) + b_i. \end{aligned} \]由于 \(a_j > a_i\),则 \(c_i' = S + a_j + a_i + b_i\)。
- 比较:\[\max(c_i, c_j) = S + a_i + a_j + b_j \quad \text{vs} \quad \max(c_j', c_i') = S + a_j + a_i + b_i. \]由 \(b_j < b_i\),显然 \(S + a_j + a_i + b_i > S + a_i + a_j + b_j\)。因此原顺序更优。
#include <iostream>
#include <algorithm>
using namespace std;
#define int long long
constexpr int N = 50001;
struct Node {
int a, b;
friend bool operator<(Node x, Node y) {
int p = min(x.a, y.b), q = min(x.b, y.a);
if (p == q) {
return x.a < y.a;
}
return p < q;
}
};
int n;
Node arr[N];
void init() {
cin >> n;
for (int i = 1; i <= n; ++i) {
cin >> arr[i].a >> arr[i].b;
}
sort(arr + 1, arr + n + 1);
}
void calculate() {
int x = 0, y = arr[1].a + arr[1].b;
for (int i = 2, sum = arr[1].a; i <= n; ++i) {
sum += arr[i].a;
x = max(y, sum) + arr[i].b;
swap(x, y);
}
cout << y << '\n';
}
void solve() {
cin.tie(nullptr)->sync_with_stdio(false);
int t;
cin >> t;
while (t--) {
init();
calculate();
}
}
signed main() {
solve();
return 0;
}

浙公网安备 33010602011771号