题意:给你一棵树,每个节点有一个权值,q次询问,每次询问求以u为根节点的子树异或上x的最大值。n,q <= 1e5
思路:要解决子树的问题,那么就是dfs序,解决异或最大值,那么就是01Trie,然后这题需就是根据dfs序建立可持
久化01Trie就好了。
代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5+5;
const int maxnode = maxn*35;
int trie[maxnode][2], sz[maxnode], rt[maxn];
int n, q, cnt, a[maxn];
int in[maxn*4], out[maxn*4], fa[maxn*4], tot;
vector<int> g[maxn];
int update(int pre, int i, int x)
{
int now = ++cnt;
if(!i)
{
trie[now][0] = trie[now][1] = 0;
sz[now] = sz[pre]+1;
return now;
}
int bt = ((x>>(i-1))&1);
trie[now][1-bt] = trie[pre][1-bt];
trie[now][bt] = update(trie[pre][bt], i-1, x);
sz[now] = sz[trie[now][0]]+sz[trie[now][1]];
return now;
}
int query(int l, int r, int i, int x)
{
if(!i) return 0;
int bt = ((x>>(i-1))&1);
if(sz[trie[r][1-bt]]-sz[trie[l][1-bt]])
return (1<<(i-1))+query(trie[l][1-bt], trie[r][1-bt], i-1, x);
else
return query(trie[l][bt], trie[r][bt], i-1, x);
}
void dfs(int u, int pre)
{
in[u] = ++tot;
rt[tot] = update(rt[tot-1], 31, a[u]);
fa[u] = pre;
for(int i = 0; i < g[u].size(); i++)
{
int v = g[u][i];
if(v != pre)
dfs(v, u);
}
out[u] = tot;
}
int main(void)
{
while(cin >> n >> q)
{
for(int i = 0; i <= n; i++)
g[i].clear();
for(int i = 1; i <= n; i++)
scanf("%d", &a[i]);
for(int i = 2; i <= n; i++)
{
int tmp;
scanf("%d", &tmp);
g[tmp].push_back(i);
}
rt[0] = trie[0][0] = trie[0][1] = sz[0] = cnt = tot = 0;
rt[0] = update(rt[0], 31, 0);
dfs(1, 0);
while(q--)
{
int u, x;
scanf("%d%D", &u, &x);
int ans = max(a[u]^x, query(rt[in[u]], rt[out[u]], 31, x));
printf("%d\n", ans);
}
}
return 0;
}

本文介绍了一种利用DFS序和持久化01Trie解决树形结构中子树异或最大值问题的方法。通过DFS遍历树并更新01Trie,实现了高效的查询与更新。
302

被折叠的 条评论
为什么被折叠?



