// 01 Trie (max xor), supports: // 1) insert(x) // 2) max_xor(x): max value of (x ^ y) among inserted y // 3) erase(x): optional (requires count maintenance)
#include<bits/stdc++.h> usingnamespace std;
template<int MAX_BIT = 30> // for int up to 1e9 use 30, for signed int full use 31 struct BinaryTrie { struct Node { int ch[2]; int cnt; // how many numbers pass this node Node() : ch{-1, -1}, cnt(0) {} };
voidinsert(int x){ int p = 0; tr[p].cnt++; for (int b = MAX_BIT; b >= 0; --b) { int bit = (x >> b) & 1; if (tr[p].ch[bit] == -1) { tr[p].ch[bit] = (int)tr.size(); tr.emplace_back(); } p = tr[p].ch[bit]; tr[p].cnt++; } }
// erase one x (assume x exists) voiderase(int x){ int p = 0; tr[p].cnt--; for (int b = MAX_BIT; b >= 0; --b) { int bit = (x >> b) & 1; p = tr[p].ch[bit]; tr[p].cnt--; } }
boolempty()const{ return tr[0].cnt == 0; }
// return max (x ^ y), y from trie intmax_xor(int x)const{ if (empty()) return0; // or throw int p = 0, ans = 0; for (int b = MAX_BIT; b >= 0; --b) { int bit = (x >> b) & 1; int want = bit ^ 1; // greedy opposite bit int nxt = tr[p].ch[want]; if (nxt != -1 && tr[nxt].cnt > 0) { ans |= (1 << b); p = nxt; } else { p = tr[p].ch[bit]; } } return ans; }
// return min (x ^ y), y from trie intmin_xor(int x)const{ if (empty()) return0; // or throw int p = 0, ans = 0; for (int b = MAX_BIT; b >= 0; --b) { int bit = (x >> b) & 1; int same = tr[p].ch[bit]; if (same != -1 && tr[same].cnt > 0) { p = same; } else { ans |= (1 << b); p = tr[p].ch[bit ^ 1]; } } return ans; } };
// ---------------- example ---------------- // int main() { // ios::sync_with_stdio(false); // cin.tie(nullptr); // // vector<int> a = {1, 2, 3, 10}; // BinaryTrie<30> bt; // for (int x : a) bt.insert(x); // // cout << bt.max_xor(5) << "\n"; // max of (5^x) // bt.erase(2); // cout << bt.max_xor(5) << "\n"; // }