题意:给出一颗树和Q个询问
对于每个询问 x y
你需要搞出 x 节点 子树上一点 (包括自己) 与 y 值异或的最大值
解题思路:
套路题
子树 → dfs序
异或极值 → trie树
dfs + trie → 可持久化trie
按连续序列建树即可
代码
/*
Zeolim - An AC a day keeps the bug away
*/
//#pragma GCC optimize(2)
//#pragma GCC ("-W1,--stack=128000000")
#include <bits/stdc++.h>
using namespace std;
#define mp(x, y) make_pair(x, y)
#define fr(x, y, z) for(int x = y; x < z; ++x)
#define pb(x) push_back(x)
#define mem(x) memset(x, 0, sizeof(x))
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
typedef std::pair <int, int> pii;
typedef std::vector <int> vi;
//typedef __int128 ill;
const ld PI = acos(-1.0);
const ld E = exp(1.0);
const ll INF = 0x3f3f3f3f3f3f3f3f;
const ll MOD = 386910137;
const ull P = 13331;
const int MAXN = 2e5 + 10;
struct trie
{
int cnt, root[MAXN], tr[MAXN * 30][2], sum[MAXN * 30];
trie() {cnt = 0;}
void insert(int now, int last, int val)
{
int nto, lto;
root[now] = nto = ++cnt;
lto = root[last];
for(int i = 30; i >= 0; --i)
{
int dig = val >> i & 1;
tr[nto][0] = tr[lto][0];
tr[nto][1] = tr[lto][1]; //½«ÉÏÒ»°æ±¾¶ù×ÓÖ±½Ó¸²¸Ç
tr[nto][dig] = ++cnt, nto = cnt; //µ±Ç°°æ±¾µÄжù×Ó
lto = tr[lto][dig];
sum[nto] = sum[lto] + 1; //ǰ׺ºÍ + 1
}
}
int get(int now, int last, int val)
{
int ret = 0;
int nto = root[now], lto = root[last];
for(int i = 30; i >= 0; --i)
{
int dig = val >> i & 1 ^ 1;
if(sum[ tr[nto][dig] ] - sum[ tr[lto][dig] ]) //µ±Ç°Çø¼äÄÚÓиÃÄ¿±ê½Úµã
ret += (1 << i), nto = tr[nto][dig], lto = tr[lto][dig];
else
nto = tr[nto][dig ^ 1], lto = tr[lto][dig ^ 1];
}
return ret;
}
void clear()
{
cnt = 0;
mem(sum);
mem(tr);
mem(root);
}
}T;
int val[MAXN] = {0};
int fa[MAXN] = {0};
vector <int> edge[MAXN];
int arr[MAXN] = {0}, tot = 0;
int in[MAXN] = {0}, out[MAXN] = {0};
void gao(int now)
{
arr[++tot] = val[now];
in[now] = tot;
for(auto x :edge[now])
gao(x);
out[now] = tot;
}
void clear(int n)
{
T.clear();
for(int i = 0; i <= n; ++i)
edge[i].clear();
tot = 0;
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
int n, q;
while(cin >> n >> q)
{
clear(n);
for(int i = 1; i <= n; ++i)
cin >> val[i];
for(int i = 2; i <= n; ++i)
{
cin >> fa[i];
edge[fa[i]].push_back(i);
}
gao(1);
T.insert(0, 0, 0);
for(int i = 1; i <= n; ++i)
{
T.insert(i, i - 1, arr[i]);
}
int x, y;
while(q--)
{
cin >> x >> y;
cout << T.get(out[x], in[x] - 1, y) << '\n';
}
}
return 0;
}
/*
5 5
5 2 7 3 1
3 1 1 3
1 5
3 2
4 3
2 1
5 5
*/