New techniques learnt: Trie can be used for some XOR problems. The basic idea: we build a MSB->LSB prefix Trie of all numbers; then query greedily: find an existing XOR-diff bit at each target bit index.
I found a clean and easy-to-understand code on LeaderBoard, from user pedrosorio
#include <cstdio> #include <cstring> #include <iostream> #include <sstream> #include <set> #include <string> #include <algorithm> #include <vector> #include <unordered_map> #include <unordered_set> using namespace std; #define MAX_NODE 100000 #define MAX_MASK 32768 struct Node { vector<int> inxes; Node *child[2]; // 0 - left, 1 - right Node() { child[0] = child[1] = nullptr; } }; void insert(Node *root, int val, int inx) { int mask = 1 << 14; int branch; Node *p = root; while (mask > 0) { branch = (mask & val) ? 1 : 0; if (p->child[branch] == nullptr) p->child[branch] = new Node(); p = p->child[branch]; p->inxes.push_back(inx); mask >>= 1; } } void treeDelete(Node *root) { if (root) { treeDelete(root->child[0]); treeDelete(root->child[1]); delete root; } } // If any existed index in inds is within [p, q] bool inRange(vector<int> &inds, int p, int q) { int min = 0, max = inds.size() - 1; int vmin = inds[min], vmax = inds[max]; int mid, vmid; if (vmin > q || vmax < p) return false; if (vmin >= p || vmax <= q) return true; // Binary search // we need it, because [p,q] may fall into a gap while (max > min + 1) { mid = (max + min) / 2; vmid = inds[mid]; if (vmid < p) min = mid; else if (vmid > q) max = mid; else return true; } return false; } int treeMaxOr(Node *root, int a, int p, int q) { int mask = 1 << 14, branch, ret = 0; Node *ptr = root; while (mask > 0) { branch = (mask & a) ? 0 : 1; if (ptr->child[branch] && inRange(ptr->child[branch]->inxes, p, q)) { ret += mask; // found a diff. } else { branch = 1 - branch; } ptr = ptr->child[branch]; mask >>= 1; } return ret; } int main() { int t; cin >> t; while (t--) { Node *root = new Node(); int n, q; cin >> n >> q; for (int i = 0; i < n; i++) { int x; cin >> x; insert(root, x, i + 1); } while (q--) { int a, p, q; cin >> a >> p >> q; cout << treeMaxOr(root, a, p, q) << endl; } treeDelete(root); } return 0; }
A more important lesson learnt: visualize the procdure in your mind, and you will probably close to the smart solution!