题意:给你一棵有根树,树上每个节点有一个值,每次询问以u为根节点的子树异或上x的最大值。
题解:按照dfs序建关于数字的二进制可持久化字典树就好了= =
AC代码:
#include<stdio.h>
#include<vector>
#include<string.h>
#define N 100005
using namespace std;
int a[N];
vector<int>vt[N];
int tree[N*35][2],son[N*35][2],root[N],tot,index;
int tou[N],la[N];
void build(int last,int cur,int num,int pos)
{
if(pos<0)return ;
int temp=(num&(1<<pos))>0;
tree[cur][temp]=tree[last][temp]+1;
tree[cur][temp^1]=tree[last][temp^1];
son[cur][temp^1]=son[last][temp^1];
build(son[last][temp],son[cur][temp]=++tot,num,pos-1);
}
void dfs(int u)
{
la[u]=++index;
build(root[la[u]-1],root[la[u]]=++tot,a[u],30);
for(int i=0;i<vt[u].size();i++)
{
int to=vt[u][i];
dfs(to);
}
tou[u]=index;
}
int query(int last,int cur,int num,int sum,int pos)
{
if(pos<0)return sum;
int temp=!!(num&(1<<pos));
if(tree[cur][temp^1]-tree[last][temp^1]>0)return query(son[last][temp^1],son[cur][temp^1],num,sum|(1<<pos),pos-1);
else return query(son[last][temp],son[cur][temp],num,sum,pos-1);
}
int main()
{
int n,q;
while(~scanf("%d%d",&n,&q))
{
memset(son,0,sizeof(son));
memset(tree,0,sizeof(tree));
memset(root,0,sizeof(root));
tot=index=0;
for(int i=0;i<100005;i++)vt[i].clear();
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
for(int i=2;i<=n;i++)
{
int u;
scanf("%d",&u);
vt[u].push_back(i);
}
dfs(1);
while(q--)
{
int u,x;
scanf("%d%d",&u,&x);
printf("%d\n",query(root[la[u]-1],root[tou[u]],x,0,30));
}
}
}