题目
题解
如果每次查询都是在整棵树查询的话,那么直接用01字典树就可以解决。但是如果查询是在某一子树的话,就没法在线的查询了,需要进行离线处理。用 dfs 从下向上建树,在遇到非叶子结点时,对其子节点进行合并。之所以叫启发式合并,是因为我们通常把将小向大的合并叫做启发式合并。
PS. 代码最后注释了一组样例,莫名WA的同学可以试试
代码
#include <algorithm>
#include <bitset>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <climits>
#include <iostream>
#include <list>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <vector>
using namespace std;
const int MAX = 100005;
struct trieNode
{
trieNode *to[2];
int num;
long long val;
trieNode(int num = 0, int val = 0){
memset(to,NULL, sizeof(to));
this->num = num;
this->val = val;
}
};
void inser(long long a, trieNode *u){
for(int i=32;i>=0;i--){
int c = ((a>>i)&1);
if(u->to[c] == NULL){
u->to[c] = new trieNode();
}
(u->to[c])->num++;
u = u->to[c];
}
u->val = a;
}
long long query(long long a,trieNode *u){
for(int i=32;i>=0;i--){
int c=((a>>i)&1);
if(u->to[c^1] )
u = u->to[c^1];
else
u = u->to[c];
}
return u -> val;
}
void clear(trieNode *u){
if(u -> to[0])
clear(u -> to[0]);
if(u -> to[1])
clear(u -> to[1]);
free(u);
}
trieNode* Merge(trieNode *a, trieNode *b){
if(a == NULL) return b;
if(b == NULL) return a;
a -> to[0] = Merge(a -> to[0], b -> to[0]);
a -> to[1] = Merge(a -> to[1], b -> to[1]);
a -> num += b -> num;
free(b);
return a;
}
struct node{
int id;
int x;
};
vector<struct node>v[MAX];
int ans[MAX];
struct MyMap{
struct edge{
int to,next,val;
}edges[MAX];
int head[MAX];
int value[MAX];
int cnt;
void init(){
cnt = 0;
memset(head,-1,sizeof(head));
}
void addEdge(int u, int v, int val){
edges[cnt].to = v;
edges[cnt].val = val;
edges[cnt].next = head[u];
head[u] = cnt++;
}
trieNode* dfs(int u){
trieNode *root = new trieNode();
for(int i=head[u];i != -1;i=edges[i].next){
int v = edges[i].to;
trieNode* temp;
temp = dfs(v);
root = Merge(root,temp);
}
inser(value[u],root);
int len = v[u].size();
for(int i=0;i<len;++i) {
ans[v[u][i].id] = query(v[u][i].x,root) ^ v[u][i].x;
}
return root;
}
};
MyMap myMap;
int main(){
int n,q;
while(cin >> n >> q){
myMap.init();
for(int i=1;i<=n;++i){
scanf("%d",&myMap.value[i]);
v[i].clear();
}
for(int i=1;i<=n-1;++i){
int x;
scanf("%d",&x);
myMap.addEdge(x, i+1, 0);
}
struct node temp;
for(int i=0;i<q;++i){
int u,x;
scanf("%d %d",&u,&x);
temp.id = i;
temp.x = x;
v[u].push_back(temp);
}
clear(myMap.dfs(1));
for(int i=0;i<q;++i){
printf("%d\n",ans[i]);
}
}
return 0;
}
/*
2 2
1 2
1
1 3
2 1
11 4
1 2 3 4 5 6 7 8 9 10 11
1 1 1 2 2 3 4 4 4 5
2 5
3 6
1 2
8 7
*/