Query on A Tree
Time Limit: 20000/10000 MS (Java/Others) Memory Limit: 132768/132768 K (Java/Others)Total Submission(s): 76 Accepted Submission(s): 31
Problem Description
Monkey A lives on a tree, he always plays on this tree.
One day, monkey A learned about one of the bit-operations, xor. He was keen of this interesting operation and wanted to practise it at once.
Monkey A gave a value to each node on the tree. And he was curious about a problem.
The problem is how large the xor result of number x and one node value of label y can be, when giving you a non-negative integer x and a node label u indicates that node y is in the subtree whose root is u(y can be equal to u).
Can you help him?
One day, monkey A learned about one of the bit-operations, xor. He was keen of this interesting operation and wanted to practise it at once.
Monkey A gave a value to each node on the tree. And he was curious about a problem.
The problem is how large the xor result of number x and one node value of label y can be, when giving you a non-negative integer x and a node label u indicates that node y is in the subtree whose root is u(y can be equal to u).
Can you help him?
Input
There are no more than 6 test cases.
For each test case there are two positive integers n and q, indicate that the tree has n nodes and you need to answer q queries.
Then two lines follow.
The first line contains n non-negative integers V1,V2,⋯,Vn , indicating the value of node i.
The second line contains n-1 non-negative integers F1,F2,⋯Fn−1 , Fi means the father of node i+1 .
And then q lines follow.
In the i-th line, there are two integers u and x, indicating that the node you pick should be in the subtree of u, and x has been described in the problem.
2≤n,q≤105
0≤Vi≤109
1≤Fi≤n , the root of the tree is node 1.
1≤u≤n,0≤x≤109
For each test case there are two positive integers n and q, indicate that the tree has n nodes and you need to answer q queries.
Then two lines follow.
The first line contains n non-negative integers V1,V2,⋯,Vn , indicating the value of node i.
The second line contains n-1 non-negative integers F1,F2,⋯Fn−1 , Fi means the father of node i+1 .
And then q lines follow.
In the i-th line, there are two integers u and x, indicating that the node you pick should be in the subtree of u, and x has been described in the problem.
2≤n,q≤105
0≤Vi≤109
1≤Fi≤n , the root of the tree is node 1.
1≤u≤n,0≤x≤109
Output
For each query, just print an integer in a line indicating the largest result.
Sample Input
2 2 1 2 1 1 3 2 1
Sample Output
2 3
Source
思路:离线存下询问。每个节点建立一棵01字典树,然后从根节点开始,对于这个节点的询问,去计算最大值,然后把叶子节点与它的父亲节点合并成一个树,然后再做该层的询问。
#pragma comment(linker, "/STACK:102400000,102400000")
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<vector>
using namespace std;
#define maxn 100005
typedef struct tree{
tree *nxt[2];
}tree;
typedef struct {
int x;
int id;
}res;
tree *root[maxn];
vector<int>vec[maxn];
vector<res>Q[maxn];
int val[maxn],ans[maxn];
void Update(tree *q,int a){
int now;
tree *p = q;
for(int i = 29;i >= 0;i--){
now = 0;
if(a & (1 << i)) //判断当前位是0还是1
now = 1;
if(p->nxt[now] == NULL){
tree *tmp = new tree;
tmp->nxt[0] = tmp->nxt[1] = NULL;
p->nxt[now] = tmp;
}
p = p->nxt[now];
}
}
int Query(tree *q,int a){
int now;
int tmp = 0;
tree *p = q;
for(int i = 29;i >= 0;i--){
now = 0;
if(a & (1 << i)) //判断当前为
now = 1;
if(p->nxt[now ^ 1] != NULL){ // now ^ 1 = 0 则 now 为 1 ,它最佳匹配是 0 ,这里贪心
p = p->nxt[now ^ 1];
tmp |= (1 << i); //贪心的结果就是使它成为 1
}else{
p = p->nxt[now];
}
}
return tmp;
}
tree* Merge(tree *t1,tree *t2){
if(t1 == NULL)
return t2;
if(t2 == NULL)
return t1;
t1->nxt[0] = Merge(t1->nxt[0],t2->nxt[0]);
t1->nxt[1] = Merge(t1->nxt[1],t2->nxt[1]);
free(t2);
return t1;
}
void Delete(tree *q){
if(q->nxt[0])
Delete(q->nxt[0]);
if(q->nxt[1])
Delete(q->nxt[1]);
free(q);
}
void Run(int u){
int v;
root[u] = new tree; //建树
root[u]->nxt[1] = root[u]->nxt[0] = NULL;
Update(root[u],val[u]); //上传树的指针和值,从根节点开始
printf("u = %d val[u] = %d\n",u,val[u]);
for(int i = 0;i < vec[u].size();i++){
v = vec[u][i]; //找到它的 儿子
Run(v); //儿子建树
root[u] = Merge(root[u],root[v]); // 合并 u 和 它的子树
}
// 从叶子节点开始
for(int i = 0;i < Q[u].size();i++){ //对于 u 层的询问,做计算,存答案 ,计算完就与根节点合并
ans[Q[u][i].id] = Query(root[u],Q[u][i].x);
}
}
int main(){
int n,q,x,y;
res tmp;
while(scanf("%d %d",&n,&q) != EOF){
memset(ans,0,sizeof(ans));
for(int i = 1;i <= n;i++){
Q[i].clear();
vec[i].clear();
scanf("%d",&val[i]);
}
for(int i = 2;i <= n;i++){
scanf("%d",&x);
vec[x].push_back(i); // vec[x] 存的是 x 的儿子
}
for(int i = 1;i <= q;i++){
scanf("%d %d",&y,&x);
tmp.x = x; //第 y 层的查询
tmp.id = i;
Q[y].push_back(tmp);
}
Run(1);
for(int i = 1;i <= q;i++)
printf("%d\n",ans[i]);
Delete(root[1]);
}
return 0;
}