01字典树在异或问题的查询上十分高效,它是按位插入和查询的,因为一个数若它的高位较大,那么这个数的值较大。所以插入和查询都是从最高位开始进行的。
1. 01字典树是一棵最多32层的二叉树,其每个节点的两条边分别代表二进制的某一位的值为0还是1.将某个路径上的值连起来就得到一个二进制串
2. ch[i]表示一个节点,ch[i][0]和ch[i][1]表示节点的两条边指向的节点,val[i]表示节点的值
3. 每个节点主要是4个属性:节点值、节点编号、两条边指向的下一节点的标号
4. 节点val值为0时表示到当前节点为止不能形成一个数,否则val[i]=数值
5. 可以通过贪心的策略来寻找与X异或结果最大的数,即优先找和X二进制的未处理的最高位值不相同的边对应的点,这样结果最大
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e5 + 5;
int tol; //节点标号
ll val[maxn * 32]; //点的值
int ch[maxn * 32][2]; //边的值
void init() {
tol = 1;
ch[0][0] = ch[0][1] = 0;
}
//向01字典树中插入x
void insert(ll x) {
int u = 0;
for(int i = 32; i >= 0; --i) {
int v = (x >> i) & 1;
if(!ch[u][v]) { //初始化节点
ch[tol][0] = ch[tol][1] = 0; //当前节点的边初始化
val