Query on A Tree
Time Limit: 20000/10000 MS (Java/Others) Memory Limit: 132768/132768 K (Java/Others)
Total Submission(s): 2867 Accepted Submission(s): 910
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?
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
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
Recommend
liuyiding
题目大意:给一个有根树,每一个点有一个点权,每次查询问子树中的某一个数与一个给定的k的异或最大值。
解题思路:dfs自底向上进行字典树的合并即可。
#include<bits/stdc++.h>
#define LL long long
#define pb(x) push_back(x)
#define sca(x) scanf("%d",&x)
#define mp(x,y) make_pair(x,y)
using namespace std;
const int N = 2e5+5;
struct node
{
int nt[3];
}t[N*30];
int root[N],a[N];
int tot;
vector<int>v[N];
typedef pair<int,int>pii;
vector<pii>Q[N];
int ou[N];
int _new( )
{
++tot;
t[tot].nt[0]=t[tot].nt[1]=0;
return tot;
}
void _ins(int &p,int val)
{
if(p==0)p=_new();
int now=p;
for(int i=30;i>=0;i--){
int id=(val>>i)&1;
if(t[now].nt[id]==0){
t[now].nt[id]=_new( );
}
now=t[now].nt[id];
}
}
int _merge(int now,int pre)
{
if(now==0||pre==0)return now+pre;
t[now].nt[0]=_merge(t[now].nt[0],t[pre].nt[0]);
t[now].nt[1]=_merge(t[now].nt[1],t[pre].nt[1]);
return now;
}
int ask(int root,int val)
{
int ans=0;
for(int i=30;i>=0;i--){
int id=(val>>i)&1;
if(t[root].nt[id^1]){
ans |=(1<<i);
root=t[root].nt[id^1];
}else {
root=t[root].nt[id];
}
}
return ans;
}
void dfs(int u,int fa)
{
_ins(root[u],a[u]);
for(int i=0;i<v[u].size();i++){
int to=v[u][i];
if(to!=fa){
dfs(to,u);
root[u]=_merge(root[u],root[to]);
}
}
for(int i=0;i<Q[u].size();i++){
pii tmp=Q[u][i];
ou[tmp.second]=ask(root[u],tmp.first);
}
}
void init(int n)
{
for(int i=0;i<=n;i++)v[i].clear(),Q[i].clear();
memset(ou,0,sizeof(ou));
memset(root,0,sizeof(root));
tot=0;
}
int main()
{
int n,q;
while(cin>>n>>q)
{
init(n);
for(int i=1;i<=n;i++){
sca(a[i]);
}
for(int i=1;i<=n-1;i++){
int fa;
sca(fa);
v[i+1].pb(fa);
v[fa].pb(i+1);
}
for(int i=1;i<=q;i++){
int u,k;
sca(u),sca(k);
Q[u].pb(mp(k,i));
}
dfs(1,0);
for(int i=1;i<=q;i++)printf("%d\n",ou[i]);
}
}