【HDU 6191】Query on A Tree 【可持久化字典树】

时间:2023-03-10 03:19:51
【HDU 6191】Query on A Tree 【可持久化字典树】

题目

给出一棵有n个结点的树,树根是1,每个结点给出一个value。然后给出q个询问,每个询问给出两个整数u和x,你要在以u结点为根的子树中找出一个结点v,使得val[v] xor x最大, 并输出这个最大值

分析

显而易见的可持久化字典树,只不过这次每次查询不是查询一个区间,而是查询一棵子树。那么也很简单,我们只要预处理出dfs序然后找出每个结点以它为根的子树在dfs序中的区间。然后以这个区间建可持久化字典树就可以了。

 #include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm> using namespace std;
const int maxn=+;
int val[maxn];
int head[maxn],to[maxn],Next[maxn];
int n,q,sz;
void add_edge(int a,int b){
++sz;
to[sz]=b;Next[sz]=head[a];head[a]=sz;
}
int order[maxn],L[maxn],R[maxn],num;
void dfs(int u,int fa){
num++;
order[num]=val[u];
L[u]=num;
for(int i=head[u];i!=-;i=Next[i]){
int v=to[i];
if(v!=fa)
dfs(v,u);
}
R[u]=num;
}
int ch[maxn**][],root[maxn],sum[maxn**][],cnt,val_t[*maxn*];
void update(int x,int y,int a,int ID){
root[x]=++cnt;x=root[x];
for(int i=;i>=;i--){
int id=(a>>i)&;
sum[x][id]+=sum[y][id]+;
sum[x][!id]+=sum[y][!id];
ch[x][!id]=ch[y][!id];
ch[x][id]=++cnt;
memset(ch[cnt],,sizeof(ch[cnt]));
val_t[cnt]=;
x=ch[x][id];y=ch[y][id];
}
val_t[x]=ID;
}
int query(int x,int y,int a){
for(int i=;i>=;i--){
int id=(a>>i)&;
if(sum[x][!id]-sum[y][!id]){
x=ch[x][!id],y=ch[y][!id];
}else{
x=ch[x][id],y=ch[y][id];
}
}
return val_t[x];
}
int main(){
while(scanf("%d%d",&n,&q)!=EOF){
sz=;
cnt=;
memset(head,-,sizeof(head));
memset(sum,,sizeof(sum));
for(int i=;i<=n;i++){
scanf("%d",&val[i]);
}
for(int i=;i<=n;i++){
int a;
scanf("%d",&a);
add_edge(a,i);
}
num=;
dfs(,-);
// for(int i=1;i<=n;i++)
// printf("%d ",order[i]);
// printf("\n");
update(,,,);
for(int i=;i<=n;i++){
update(i,root[i-],order[i],i);
}
int u,x;
for(int i=;i<=q;i++){
scanf("%d%d",&u,&x);
printf("%d\n",order[query(root[R[u]],root[L[u]-],x)]^x);
}
}
return ;
}