CF817E Choosing The Commander 題解
阿新 • • 發佈:2021-11-14
有Q次操作,每次操作有三種類型,分別是
> 1 pi 把 pi 加入集合 S
> 2 pi 把 pi 從集合 S 中刪除
> 3 pi li 表示查詢集合中有多少個元素異或上 pi 後 小於 li
有Q次操作,每次操作有三種類型,分別是
1 pi 把 pi 加入集合 S
2 pi 把 pi 從集合 S 中刪除
3 pi li 表示查詢集合中有多少個元素異或上 pi 後 小於 li
0/1trie樹.顯然對於每一位,若這一位異或後比li的這一位小,那麼該結點所在的子樹異或後都必然小於li,而若與li的這一位相等,則向這邊迭代.
#include <iostream> #include <cstdio> using namespace std; const int N = 3000005; int n, tot = 1; int val[N], tree[N][2]; void add(int k, int v) { int now = 1; for (int i = (1 << 30); i; i >>= 1) { val[now] += v; bool temp = k & i; if (!tree[now][temp]) tree[now][temp] = ++tot; now = tree[now][temp]; } val[now] += v; } int query(int v, int l) { int now = 1, ans = 0; for (int i = (1 << 30); i; i >>= 1) { bool temp1 = v & i, temp2 = l & i; if (temp1 < temp2) ans += val[tree[now][0]]; if (temp1 && temp2) ans += val[tree[now][1]]; if (temp2) now = tree[now][temp1 ^ 1]; else now = tree[now][temp1]; } return ans; } int main() { ios::sync_with_stdio(false); cin >> n; for (int i = 1; i <= n; i++) { int x; cin >> x; if (x == 1) { int v; cin >> v; add(v, 1); } if (x == 2) { int v; cin >> v; add(v, -1); } if (x == 3) { int v, l; cin >> v >> l; cout << query(v, l) << endl; } } }
本文來自部落格園,作者:Kinuhata,轉載請註明原文連結:https://www.cnblogs.com/KinuhataSaiai/p/15550664.html