http://acm.hdu.edu.cn/showproblem.php?pid=6191
题意:给出一棵树,每一个结点有一个值,然后给出q个询问,每一个询问给出一个u和x,问u子树的权值与x的xor值最大。
做法:就使用01字典树,把询问都离线处理,然后dfs遍历这棵树,从叶子开始往上合并字典树,字典树的合并也很简单,直接接上就可以了,重复的,删除一个就可以了,编程难度不是很大。
#include "bits/stdc++.h"
using namespace std;
const double eps = 1e-8;
#define lowbit(x) x&-x
#define pll pair<ll,ll>
#define pii pair<int,int>
#define fi first
#define se second
#define makp make_pair
int dcmp(double x) {
if (fabs(x) < eps) return 0;
return (x > 0) ? 1 : -1;
}
typedef long long ll;
typedef unsigned long long ull;
const ull hash1 = 201326611;
const ull hash2 = 50331653;
const int N = 100000 + 10;
const int M = 2048 + 10;
const int inf = 0x3f3f3f3f;
const ll mod = 1000000000 + 7;
vector<int> g[N];
int n, q, val[N], ans[N];
vector<pii > p[N];
int root[N], nxt[N * 35][2], tot = 0;
void Insert(int x, int rt) {
int u = rt;
for (int i = 31; i >= 0; i--) {
int idx = (x >> i) & 1;
if (nxt[u][idx] == 0) nxt[u][idx] = ++tot;
u = nxt[u][idx];
}
}
int query(int x, int rt) {
int ans = 0, u = rt;
for (int i = 31; i >= 0; i--) {
int idx = (x >> i) & 1;
if (nxt[u][idx ^ 1] != 0) {
u = nxt[u][idx ^ 1];
ans |= (1 << i);
} else u = nxt[u][idx];
}
return ans;
}
int Union(int rt1, int &rt2) {
if (rt1 == 0) return rt2;
if (rt2 == 0) return rt1;
nxt[rt1][0] = Union(nxt[rt1][0], nxt[rt2][0]);
nxt[rt1][1] = Union(nxt[rt1][1], nxt[rt2][1]);
rt2 = 0;
return rt1;
}
void dfs(int u) {
///root[u] = ++tot;
Insert(val[u], root[u]);
for (int i = 0; i < g[u].size(); i++) {
int v = g[u][i];
dfs(v);
root[u] = Union(root[u], root[v]);
}
for (auto i:p[u]) {
ans[i.fi] = query(i.se, root[u]);
}
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
while (cin >> n >> q) {
for (int i = 0; i <= n; i++) {
g[i].clear();
p[i].clear();
}
memset(nxt, 0, sizeof(nxt));
///memset(root, 0, sizeof(root));
tot = n;
int u, v;
for (int i = 1; i <= n; i++) {
cin >> val[i];
root[i] = i;
}
for (int i = 2; i <= n; i++) {
cin >> u;
g[u].push_back(i);
}
for (int i = 1; i <= q; i++) {
cin >> u >> v;
p[u].push_back(makp(i, v));
}
dfs(1);
for (int i = 1; i <= q; i++) {
cout << ans[i] << endl;
}
}
return 0;
}