U725151 the cure
题目背景
:::info[Solution]
因为之前是出给基础赛的所以写得比较详细。
首先需要特判掉 $n = 1$ 的情况,此时无法进行任何操作,答案为 $S_1$。
容易发现,为了通过操作获得一个 $x$,最优的操作是选择 $T = \{0, 1, \dots, x - 1\}$,因为如果有多余的元素显然可以去掉。
发现直接贪心没有正确性或难以实现。注意到答案(在 $n \gt 1$ 时)有单调性,因此考虑二分。考虑怎么判定,发现想要凑出 $x$,我们需要 $0$ 到 $x - 1$ 各一个;于是我们又可以考虑怎么凑出一个 $x - 1$;依次类推,发现最后的限制是至少需要多少个 $0$,于是我们只需要在过程中统计 $0$ 的数量即可。
设 $c_j$ 表示 $j$ 的数量。具体地,设当前考虑了 $i$,有 $s$ 个 $0$,需要 $0$ 到 $i - 1$ 各 $r$ 个。
- 初始时 $i = x$;对 $\ge x$ 的每个数操作一次变为 $0$,因此有 $s = c_0 + \sum_{j = x}^n c_j$ 个 $0$;需要 $0$ 到 $x - 1$ 各一个,因此 $r = 1$。
- 从 $x - 1$ 到 $1$ 依次枚举 $i$。
- 若 $c_i \ge r$,那么可以将多余的 $c_i - r$ 个 $i$ 各操作一次变为 $0$,因此令 $s' \leftarrow s + c_i - r$。
- 若 $c_i \lt r$,那么还需要额外的 $r - c_i$ 个 $i$,将这一部分转化为 $0$ 到 $i - 1$ 各 $r - c_i$ 个,因此令 $r' \leftarrow r + r - c_i$。
最终,若 $s \ge r$ 那么答案 $x$ 合法,否则不合法。注意过程中 $r$ 是 $O(2^n)$ 的,所以当 $r \gt n$ 时可以直接判定为不合法。注意到答案的上界是 $n$,因此可以将 $\ge n$ 的数直接变为 $0$。
时间复杂度 $O(n \log n)$。
```cpp
int n, s, cnt[1000005];
bool chk(int x) {
int sum = cnt[0], req = 1;
rep(i, x, n) sum += cnt[i];
_rep(i, x - 1, 1) {
if(cnt[i] < req) req += req - cnt[i];
else sum += cnt[i] - req;
if(req > n) return 0;
}
return sum >= req;
}
void solve() {
cin >> n;
rep(i, 0, n) cnt[i] = 0;
rep(i, 1, n) cin >> s, ++cnt[s > n ? 0 : s];
if(n == 1) return cout
题目描述
给定一个大小为 $n$ 的可重集 $S$。你可以进行若干次(包括 $0$ 次)如下操作,直至集合的大小变为 $1$:
- 选择 $S$ 的一个非空子集 $T$,从 $S$ 中移除 $T$ 的所有元素,并将 $\operatorname{mex}(T)$ 加入到 $S$ 中。形式化地:$S \leftarrow (S \setminus T) \cup \{\operatorname{mex}(T)\}$,其中 $\operatorname{mex}(T)$ 定义为集合 $T$ 中未出现的最小非负整数。
你的目标是使操作结束时集合中仅剩的元素 $x$ 最大化。请输出 $x$ 的最大值。
请注意,当集合大小为 $1$ 时你不能再进行任何操作。
输入格式
**本题单个测试点内有多组测试数据。**
第一行,包含一个整数 $T$,表示测试数据的组数。
对于每组数据:
- 第一行,包含一个正整数 $n$,表示可重集 $S$ 的大小。
- 第二行,包含 $n$ 个非负整数,表示可重集 $S$ 的元素 $S_1, S_2, \dots, S_n$。
输出格式
$T$ 行,每行一个非负整数,表示操作结束时集合中仅剩的数 $x$ 的最大值。
说明/提示
**【样例 #1 解释】**
对于第一组测试数据,一种最优的操作序列如下:
- 选择 $T = \{0\}$,操作后 $S = \{0, 1\}$。
- 选择 $T = \{0, 1\}$,操作后 $S = \{2\}$
- 此时集合大小为 $1$,$x = 2$,停止操作。
可以证明,不存在操作序列使得答案大于 $2$。
对于第二组测试数据,一种可能的操作序列如下:
- 选择 $T = \{2, 4\}$,$S$ 变为 $\{0, 0, 1\}$。
- 选择 $T = \{0, 0, 1\}$,$S$ 变为 $\{2\}$。
- 此时集合大小为 $1$,$x = 2$,停止操作。
可以证明,不存在操作序列使得答案大于 $3$。
**【数据范围】**
设 $\sum n$ 表示单个测试点中每组数据的 $n$ 之和。
::cute-table{tuack}
| 子任务 | $\sum n$ | 特殊性质 | 依赖 | 分值 |
| :----: | :--------: | :--------------------------------: | :--------: | :--: |
| $1$ | $\le 10$ | 无 | 无 | $10$ |
| $2$ | $\le 100$ | ^ | $1$ | $15$ |
| $3$ | $\le 1000$ | ^ | $2$ | $15$ |
| $4$ | $\le 10^6$ | $S$ 中 $0$ 到 $n - 1$ 各出现了一次 | 无 | $10$ |
| $5$ | ^ | $S_i = 0$ | ^ | $15$ |
| $6$ | ^ | $S_i \le 10$ | $5$ | $15$ |
| $7$ | ^ | 无 | $1 \sim 6$ | $20$ |
对于所有数据,保证:
- $1 \le T \le 10^6$。
- $1 \le n, \sum n \le 10^6$。
- $\forall i \in [1, n], 0 \le S_i \le 10^9$。