HDU 6191 Query on A Tree
可持久字典树。
询问子树可以转化为询问一段区间,因此可以对树的$dfs$序进行操作。因为是在一群数字中找一个数字和已知数字异或最大,所以可以想到字典树。保存前缀字典树,然后询问区间$[L,R]$的时候,只要$R$的字典树减去$L-1$的字典树就是区间$[L,R]$上的的数字构成的字典树。
#include <bits/stdc++.h>
using namespace std;
const int maxn = 100000 + 10;
int n, a[maxn];
int sz, h[maxn], to[maxn], nx[maxn];
int L[maxn], R[maxn];
int num, b[2 * maxn];
int q;
struct Node {
int son[2];
int cnt;
}s[65 * maxn];
int root[2 * maxn];
void addedge(int u, int v) {
to[sz] = v;
nx[sz] = h[u];
h[u] = sz;
sz ++;
}
void dfs(int x) {
b[++ num] = a[x];
L[x] = num;
for(int i = h[x]; i != -1; i = nx[i]) {
dfs(to[i]);
}
b[++ num] = a[x];
R[x] = num;
}
int addnode() {
num ++;
s[num].son[0] = -1;
s[num].son[1] = -1;
s[num].cnt = 0;
return num;
}
int work(int x, int y) {
int res = 0;
int p1 = root[L[x] - 1];
int p2 = root[R[x]];
for(int i = 30; i >= 0; i --) {
int u = (1 << i) & y;
u = u ? 1 : 0;
if(p1 == -1) {
if(s[p2].son[u ^ 1] != -1) {
res = res + (1 << i);
p2 = s[p2].son[u ^ 1];
} else {
p2 = s[p2].son[u];
}
} else {
if(s[p2].son[u ^ 1] == -1) {
p1 = s[p1].son[u];
p2 = s[p2].son[u];
} else {
if(s[p1].son[u ^ 1] == -1) {
res = res + (1 << i);
p1 = s[p1].son[u ^ 1];
p2 = s[p2].son[u ^ 1];
} else {
if(s[s[p1].son[u ^ 1]].cnt < s[s[p2].son[u ^ 1]].cnt) {
res = res + (1 << i);
p1 = s[p1].son[u ^ 1];
p2 = s[p2].son[u ^ 1];
} else {
p1 = s[p1].son[u];
p2 = s[p2].son[u];
}
}
}
}
}
return res;
}
int main() {
while(~scanf("%d%d", &n, &q)) {
num = sz = 0;
for(int i = 1; i <= n; i ++) {
h[i] = -1;
}
for(int i = 1; i <= n; i ++) {
scanf("%d", &a[i]);
}
for(int i = 1; i <= n - 1; i ++) {
int x;
scanf("%d", &x);
addedge(x, i + 1);
}
dfs(1);
num = 0;
root[0] = 0;
s[0].son[0] = -1;
s[0].son[1] = -1;
s[0].cnt = 0;
for(int i = 1; i <= 2 * n; i ++) {
root[i] = addnode();
int p1 = root[i - 1];
int p2 = root[i];
s[p2].son[0] = s[p1].son[0];
s[p2].son[1] = s[p1].son[1];
s[p2].cnt = s[p1].cnt;
for(int j = 30; j >= 0; j --) {
int x = (1 << j) & b[i];
x = x ? 1 : 0;
if(p1 == -1) {
int id = addnode();
s[id].cnt ++;
s[p2].son[x] = id;
p2 = id;
} else {
p1 = s[p1].son[x];
int id = addnode();
if(p1 != -1) {
s[id].son[0] = s[p1].son[0];
s[id].son[1] = s[p1].son[1];
}
if(p1 != -1) {
s[id].cnt = s[p1].cnt + 1;
} else {
s[id].cnt = 1;
}
s[p2].son[x] = id;
p2 = id;
}
}
}
for(int i = 1; i <= q; i ++) {
int x, y;
scanf("%d%d", &x, &y);
int ans = work(x, y);
printf("%d\n", ans);
}
}
return 0;
}

浙公网安备 33010602011771号