题意
给出一些数,每次操作先将所有数异或一个值,再求这些数中没有出现过的最小的非负整数。
分析
对于更新操作,对于 \(x\) 所有为 \(1\) 的位给相应层添加一个标记,当查询时走到这一层,如果有这个标记,就要把左子树当作右子树,右子树当做左子树。
对于查询操作,显然优先走左子树,如果左子树已经满了,才走右子树,并且答案就要加上对应的层的值,如果发现无路可走,说明后面可以全部取\(0\)了。code
#includeusing namespace std;typedef long long ll;const int MAXN = 1e6 + 100;struct Trie { int val[MAXN], nxt[MAXN][2], L, root, siz[MAXN], flg[21]; int newnode() { memset(nxt[L], -1, sizeof nxt[L]); return L++; } void init() { L = 0; root = newnode(); } void insert(int x) { int now = root; for(int i = 20; i >= 0; i--) { int o = ((x >> i) & 1); if(nxt[now][o] == -1) { nxt[now][o] = newnode(); } now = nxt[now][o]; siz[now]++; } } void update(int q) { for(int i = 20; i >= 0; i--) { if((q >> i) & 1) { flg[i] ^= 1; } } } int query() { int now = root; int ans = 0; for(int i = 20; i >= 0; i--) { int o = 0; if(flg[i]) o = !o; if(nxt[now][o] == -1) { break; } else { if(siz[nxt[now][o]] < (1 << i)) { now = nxt[now][o]; } else { ans |= (1 << i); if(nxt[now][!o] == -1) break; else now = nxt[now][!o]; } } } return ans; }}trie;set num;int main() { ios::sync_with_stdio(0); cin.tie(0); int n, m; cin >> n >> m; for(int i = 0; i < n; i++) { int x; cin >> x; num.insert(x); } trie.init(); for(int i : num) { trie.insert(i); } while(m--) { int q; cin >> q; trie.update(q); cout << trie.query() << endl; } return 0;}