题目链接
http://acm.hdu.edu.cn/showproblem.php?pid=6191
题意
给
你
一
颗
带
权
树
,
每
次
查
询
以
u
为
根
的
子
树
上
与
x
异
或
的
最
大
值
给你一颗带权树,每次查询以u为根的子树上与x异或的最大值
给你一颗带权树,每次查询以u为根的子树上与x异或的最大值
做法
由
于
出
现
子
树
,
我
们
就
可
以
处
理
出
d
f
s
序
由于出现子树,我们就可以处理出dfs序
由于出现子树,我们就可以处理出dfs序
之
后
在
d
f
s
序
上
按
顺
序
建
立
可
持
久
化
01
字
典
树
之后在dfs序上按顺序建立可持久化01字典树
之后在dfs序上按顺序建立可持久化01字典树
之
后
就
类
似
主
席
树
用
前
缀
和
操
作
来
获
取
某
个
区
间
的
01
字
典
树
信
息
之后就类似主席树用前缀和操作来获取某个区间的01字典树信息
之后就类似主席树用前缀和操作来获取某个区间的01字典树信息
进
行
正
常
的
01
字
典
树
查
询
异
或
最
大
值
就
可
以
了
进行正常的01字典树查询异或最大值就可以了
进行正常的01字典树查询异或最大值就可以了
代码
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string.h>
using namespace std;
typedef long long ll;
#define dbg(x) cout<<#x<<" = "<<x<<endl
const int Mod= 1000000007;
const int maxn=2e5+5;
int fa[maxn];
int val[maxn];
struct node
{
int to,nxt;
}edge[maxn];
int head[maxn],tot;
int in[maxn],out[maxn];
int num[maxn];
int coun;
void addedge(int u,int v)
{
edge[tot].to=v;
edge[tot].nxt=head[u];
head[u]=tot++;
}
void dfs(int u)
{
in[u]=++coun;
num[coun]=u;
for(int i=head[u];i+1;i=edge[i].nxt)
{
dfs(edge[i].to);
}
out[u]=coun;
}
int tt,root[maxn],son[maxn*35][2],sum[maxn*35];
bool bs[35];
void insert_(int pos,int pre,int &now)
{
now=++tot;
son[now][0]=son[pre][0],son[now][1]=son[pre][1];
sum[now]=sum[pre]+1;
if(pos==0) return ;
insert_(pos-1,son[pre][bs[pos-1]],son[now][bs[pos-1]]);
}
int query(int pos,int st,int en)
{
if(pos==0) return 0;
int tmp=sum[son[en][bs[pos-1]]]-sum[son[st][bs[pos-1]]];
if(tmp>0) return query(pos-1,son[st][bs[pos-1]],son[en][bs[pos-1]])+(1<<(pos-1));
else return query(pos-1,son[st][bs[pos-1]^1],son[en][bs[pos-1]^1]);
}
int main()
{
int n,q,u,x;
while(scanf("%d%d",&n,&q)!=EOF)
{
memset(head,-1,sizeof(head));
memset(sum,0,sizeof(sum));
tot=coun=0;
tt=1;
for(int i=1;i<=n;i++) scanf("%d",&val[i]);
for(int i=2;i<=n;i++)
{
scanf("%d",&x);
addedge(x,i);
}
dfs(1);
for(int i=1;i<=n;i++)
{
int pos=num[i];
for(int j=0;j<30;j++)
{
bs[j]=1&(val[pos]>>j);
}
insert_(30,root[i-1],root[i]);
}
for(int i=1;i<=q;i++)
{
scanf("%d%d",&u,&x);
for(int j=0;j<30;j++)
{
bs[j]=!(1&(x>>j));
}
int l=in[u],r=out[u];
printf("%d\n",query(30,root[l-1],root[r]));
}
}
}