CF817E Choosing TheCommander(01Trie)
题目链接
题意:实现三种操作\(1.\)将\(p\)加入集合中,\(2.将p\)从集合中删去,\(3.\)查询集合中所有的树在异或\(p\)之后有多少个数小于\(l\).
思路:看到跟异或的统计数字问题,所以考虑用\(01Trie\)树来实现这些操作,将\(p\)加入到集合或从集合中删除,就是很正常的\(Trie\)树的操作,将每一个数的各个二进制位都存入到树中。查询操作,考虑\(l\)当前位是\(0/1\),如果是\(0\)的话异或不会改变该位,所以继续沿着当前的路径走下去,相反出现\(1\)就将\(0\)这一分支的答案统计下来,并向相反的方向走。
constexpr int N = 5e6 + 10;
#define int i64
int tr[N][2], sum[N];
int idx = 1;
void add(int p, int z) {
int u = 1;
for (int i = 31; i >= 0; i--) {
bool x = p & (1 << i);
if (!tr[u][x]) tr[u][x] = ++idx;
u = tr[u][x];
sum[u] += z;
}
}
int query(int p, int l) {
int ans = 0, u = 1;
for (int i = 31; i >= 0; i--) {
bool x = p & (1 << i), y = l & (1 << i);
if (y) ans += sum[tr[u][x]], u = tr[u][x ^ 1];
else u = tr[u][x];
}
return ans;
}
signed main() {
std::cin.tie(nullptr)->sync_with_stdio(false);
int q; std::cin >> q;
while(q--) {
int op;
std::cin >> op;
int p; std::cin >> p;
if (op == 1) {
add(p, 1);
} else if (op == 2) {
add(p, -1);
} else {
int l; std::cin >> l;
std::cout << query(p, l) << "\n";
}
}
}

浙公网安备 33010602011771号