Query on A Tree
Time Limit: 20000/10000 MS (Java/Others) Memory Limit: 132768/132768 K (Java/Others)
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
1)维护前缀Tire树,用可持久化降低复杂度
2)静态维护方便
#include <string>
#include <stdlib.h>
#include <vector>
#include <algorithm>
#include <string.h>
#include <stdio.h>
#include <set>
#include <iostream>
#include <algorithm>
#include <map>
#include <queue>
#include <math.h>
#include<iostream>
using namespace std;
typedef long long LL ;
const int N = 100008 ;
std::vector<int> adj[N] ;
int _left[N], _right[N] ;
int dfn ;
void dfs(int u) {
_left[u] = ++dfn ;
for(std::vector<int>::iterator it = adj[u].begin() ; it != adj[u].end() ; it++) {
dfs(*it) ;
}
_right[u] = dfn ;
}
int bit[32] ;
int v[N], c[N] ;
int root[N * 32] ;
int _next[N * 32][2] ;
int cnt[N * 32] ;
int total ;
int copyNode(int x) {
total++ ;
_next[total][0] = _next[x][0] ;
_next[total][1] = _next[x][1] ;
cnt[total] = cnt[x] + 1 ;
return total ;
}
int add(int t, int val) {
int _t = copyNode(t) ;
int now = _t ;
for(int i = 30 ; i >= 0 ; i--) {
int son = (val & bit[i]) > 0 ? 1 : 0 ;
_next[now][son] = copyNode(_next[now][son]) ;
now = _next[now][son] ;
}
return _t ;
}
int query(int l, int r, int val) {
int result = 0 ;
for(int i = 30 ; i >= 0 ; i--) {
int son = (val & bit[i]) > 0 ? 1 : 0 ;
son ^= 1 ;
if(cnt[_next[r][son]] - cnt[_next[l][son]] > 0) {
result |= bit[i] ;
l = _next[l][son] ;
r = _next[r][son] ;
} else {
l = _next[l][son ^ 1] ;
r = _next[r][son ^ 1] ;
}
}
return result ;
}
int main() {
for(int i = 0 ; i < 31 ; i++) {
bit[i] = 1 << i ;
}
int n, q, f, u, x ;
while(scanf("%d%d", &n, &q) != EOF) {
for(int i = 1 ; i <= n ; i++) {
adj[i].clear() ;
scanf("%d", &v[i]) ;
}
for(int i = 2 ; i <= n ; i++) {
scanf("%d", &f) ;
adj[f].push_back(i) ;
}
dfn = 0 ;
dfs(1) ;
total = 0 ;
cnt[0] = 0 ;
root[0] = 0;
_next[0][0] = _next[0][1] = 0 ;
for(int i = 1 ; i <= n ; i++) {
c[_left[i]] = v[i] ;
}
for(int i = 1 ; i <= n ; i++) {
root[i] = add(root[i - 1], c[i]) ;
}
while(q-- > 0) {
scanf("%d%d", &u, &x) ;
printf("%d\n", query(root[_left[u] - 1], root[_right[u]], x)) ;
}
}
return 0 ;
}