- 编程
AtCoder Beginner Contest 475题解
- @ 2026-9-13 22:29:11
E - Quiz Competition: Qualifiers
思路
回答的性质:
- 正确答案串 始终不变
- 只有两个选项
所以我们不妨把答案看成一个 01 串:记答对为 1,答错为 0。
我们再看题目要求:
- If the number of qualifiers plus the number of undetermined participants who answered the -th question correctly is at most M, then all undetermined participants who answered the -th question correctly become qualifiers.
- Otherwise, all undetermined participants who answered the -th question incorrectly become non-qualifiers.
显然,这就是 01 串字典序从大到小排序:在第一个不同的数位,1 比 0 优先。
但是,我们并不能完全地说这就是取前 大的 01 串,至少:
- 当存在多个一模一样的回答串 使得一些在前 大、另一些不在时,这些串都不能晋级
- 一次也没有答对的串,按原流程永远不会被确定为晋级,但它可能在前 大
于是我们就知道怎么判断一个串是否晋级了:
形式化地说,定义
则
把所有 01 串插入二叉字典树,高位在前,1 为右子、0 为左子。原过程等价于从根出发走一条路径 :
- 设在节点 ,其子树内有 个待定选手,右子(1)有 个,左子(0)有 个。
- 若已晋级人数 :右子树全部晋级,走向左子(0)。
- 否则:左子树全部淘汰,走向右子(1)。
走完 步得到串 。于是:
- 晋级:在首个不同位 为 1、 为 0,该步选择了走向 0,右子树(含 )已被整体晋级。
- 淘汰:它们是最后剩余的待定者。
- 淘汰:在某次「走向 1」时作为左子树被淘汰。
所以晋级集合恰好是 。下面把它化为只依赖 的条件。
-
充分性:,在首个不同位 ,故 至少答对一题。所有 的串都 ,从而都在晋级集合内,故 。
-
必要性:反设 。
- 若 : 答对至少一题说明 含 1,即某一步选择了「走向 1」(当时 已晋级 )。设该步待定集合大小为 ,则 已晋级 已晋级 ;而 已晋级 待定集合,故 ,矛盾。
- 若 :在首个不同位 、,即该步「走向 1」,有 已晋级 。所有 的串包含当时的右子树 个与已晋级者,故 已晋级 ,矛盾。
因此 ,即晋级。结论成立。
代码
字典树初始化时最多要插入 个节点 修改时最多又要插入 个节点,所以要注意字典树数组空间
// E - Quiz Competition: Qualifiers
#include <iostream>
using namespace std;
const int N = 3e4 + 1023;
int n, m, k, son[2 * N * 200][2], idx, cnt[2 * N * 200], q, num[N];
string t, s[N];
void insert(string s) {
int p = 0;
for (int i = 0; i < k; i++) {
int v = s[i] == t[i];
if (!son[p][v]) son[p][v] = ++idx;
p = son[p][v];
cnt[p]++;
}
}
void remove(string s) {
int p = 0;
for (int i = 0; i < k; i++) {
int v = s[i] == t[i];
p = son[p][v];
cnt[p]--;
}
}
int query(string s) {
int p = 0, res = 0;
for (int i = 0; i < k; i++) {
int v = s[i] == t[i];
if (v == 0) res += cnt[son[p][1]];
p = son[p][v];
}
res += cnt[p];
return res;
}
int main() {
cin >> n >> m >> k >> t;
for (int i = 1; i <= n; i++) {
cin >> s[i];
insert(s[i]);
for (int j = 0; j < k; j++)
num[i] += s[i][j] == t[j];
}
cin >> q;
for (int i, j; q--;) {
cin >> i >> j;
remove(s[i]);
s[i][j - 1] = s[i][j - 1] == 'o' ? 'x' : 'o';
if (s[i][j - 1] == t[j - 1]) num[i]++;
else num[i]--;
insert(s[i]);
if (num[i] > 0 && query(s[i]) <= m) puts("Yes");
else puts("No");
}
return 0;
}
0 条评论
目前还没有评论...