1 条题解
-
0
CF1988B Make Majority 题解
题意简述
给定一个长度为 的 01 序列 。每次操作可以选择一个区间 ,统计区间内 的个数 和 的个数 :
- 若 ,则将区间替换为一个 ;
- 若 ,则将区间替换为一个 。
问能否通过若干次操作使得最终序列变为 。
核心分析
目标是把整个序列合并成单个 ,这意味着我们需要尽量减少 的数量。
关键观察 1:先合并连续的
考虑任意一段连续的 (形如
000...0,两端或一端有 隔开):- 如果我们单独对这一段连续的 做一次操作,显然 (因为 ),所以它一定会变成一个 。
- 这相当于把「一段连续 」压缩成一个 ,且该操作不会影响 的个数。
因此,我们可以先执行这样的操作,把原序列中每一段连续的 都压缩成一个单独的 。此时序列中不会出现相邻的两个 。
关键观察 2:判断最终可能性
压缩后,令整个序列中 的个数为 (也就是原序列中连续 的段数), 的个数为 。
现在考虑能否通过后续操作使整个序列合并成 :
-
如果 : 无论选择什么区间,区间内 的个数永远 的个数(因为我们可以把 和 配对,而 多了至少一个),所以任何合并操作都会倾向于产生 。最终无论如何都无法消除所有的 ,故答案为
No。 -
如果 : 我们直接选择整个序列 进行一次操作。此时区间内 ,合并结果恰好为 ,序列变为 。故答案为
Yes。
因此,判定条件仅取决于:压缩后 的个数是否严格小于 的个数。
统计方法
遍历一遍字符串:
- 遇到
'1',c1加一; - 遇到
'0',如果它是某个连续 块的开头(即 或前一个字符是'1'),则c0加一。
最后比较 与 即可。
复杂度
- 时间复杂度:。
- 空间复杂度:。
参考代码
#include <bits/stdc++.h> using namespace std; int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int T; cin >> T; while (T--) { int n, c0 = 0, c1 = 0; string a; cin >> n >> a; for (int i = 0; i < n; i++) { if (a[i] == '1') { c1++; } else { if (i == 0 || a[i-1] == '1') { c0++; } } } if (c0 >= c1) { cout << "No\n"; } else { cout << "Yes\n"; } } return 0; }
- 1
信息
- ID
- 6822
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者