Query on A Tree
Time Limit: 20000/10000 MS (Java/Others) Memory Limit: 132768/132768 K (Java/Others)Total Submission(s): 54 Accepted Submission(s): 17
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
Recommend
liuyiding | We have carefully selected several similar problems for you: 6193 6192 6191 6190 6189
解题思路:我们用dfs序把节点hash到一个数组,然后对这个数组建n棵前缀字典树就行,每次查询直接用历史版本搞就行。跟区间第k小一个道理
#define OPENSTACK #include <bits/stdc++.h> using namespace std; const int maxn = 100000 + 10; int n, q; int cnt, tot; int Rank[maxn];//节点在数组上的位置 int L[maxn];//dfs进入时间戳 int R[maxn];//dfs出时间戳 int v[maxn];//顶点权值 int T[maxn];//n棵字典树的根节点 struct node{ int sum; int l, r; node(){ sum = 0; l = 0; r = 0; } }Tree[maxn<<6]; int head[maxn]; int ee = 0; struct edge{ int v; int last; }Edge[maxn]; void add(int u, int v) { Edge[ee].v = v; Edge[ee].last = head[u]; head[u] = ee++; } void dfs(int u) { L[u] = ++cnt; for(int i = head[u]; i != -1 ; i = Edge[i].last) { int v = Edge[i].v; dfs(v); } R[u] = cnt; } void Insert(int root, int x, int value) { int p = root; for(int i = 30; i >= 0; i--) { int num = (x>>i)&1; if(num == 0) { if(Tree[p].l == 0) { Tree[p].l = tot++; p = Tree[p].l; Tree[p].sum += value; } else { p = Tree[p].l; Tree[p].sum += value; } } else { if(Tree[p].r == 0) { Tree[p].r = tot++; p = Tree[p].r; Tree[p].sum += value; } else { p = Tree[p].r; Tree[p].sum += value; } } } } int update(int pa, int x) { int now = tot++; int p = now; for(int i = 30; i >= 0; i--) { int num = (x>>i)&1; if(num == 0) { Tree[p].r = Tree[pa].r; Tree[p].l = tot++; p = Tree[p].l; pa = Tree[pa].l; Tree[p].sum = Tree[pa].sum + 1; } else { Tree[p].l = Tree[pa].l; Tree[p].r = tot++; p = Tree[p].r; pa = Tree[pa].r; Tree[p].sum = Tree[pa].sum + 1; } } return now; } int query(int p1, int p2, int x) { int d; int ans = 0; for(int i = 30; i >= 0; i--) { int num = (x>>i)&1; if(num == 0) { if(Tree[p2].r == 0) { p2 = Tree[p2].l; p1 = Tree[p1].l; continue; } d = Tree[Tree[p2].r].sum - Tree[Tree[p1].r].sum; if(d > 0) { ans += (1<<i); p1 = Tree[p1].r; p2 = Tree[p2].r; } else { p1 = Tree[p1].l; p2 = Tree[p2].l; } } else { if(Tree[p2].l == 0) { p2 = Tree[p2].r; p1 = Tree[p1].r; continue; } d = Tree[Tree[p2].l].sum - Tree[Tree[p1].l].sum; if(d > 0) { ans += (1<<i); p1 = Tree[p1].l; p2 = Tree[p2].l; } else { p1 = Tree[p1].r; p2 = Tree[p2].r; } } } return ans; } void init() { cnt = 0; tot = 0; dfs(1); for(int i = 1; i <= n; i++) { Rank[L[i]] = v[i]; } } int main() { #ifdef OPENSTACK int size = 128<< 20; // 64MB char *p = (char*)malloc(size) + size; #if (defined _WIN64) or (defined __unix) __asm__("movq %0, %%rsp\n" :: "r"(p)); #else __asm__("movl %0, %%esp\n" :: "r"(p)); #endif #endif // #ifdef OPENSTACK // exit(0); // #else // return 0; // #endif OPENSTACK; //freopen("C:\\Users\\creator\\Desktop\\in.txt","r",stdin) ; //freopen("C:\\Users\\creator\\Desktop\\out.txt","w",stdout) ; while(~scanf("%d%d", &n, &q)) { for(int i = 0; i < (maxn<<6) - 1; i++) { Tree[i].l = 0; Tree[i].r = 0; Tree[i].sum = 0; } for(int i = 1; i <= n; i++) { scanf("%d", &v[i]); } int f; ee = 0; memset(head, -1, sizeof(head)); for(int i = 1; i < n; i++) { scanf("%d", &f); add(f, i + 1); } init(); T[0] = ++tot; for(int i = 1; i <= n; i++) { Insert(T[0], Rank[i], 1); } for(int i = 1; i <= n; i++) { Insert(T[0], Rank[i], -1); } for(int i = 1; i <= n; i++) { T[i] = update(T[i - 1], Rank[i]); } int uu, xx; for(int i = 1; i <= q; i++) { scanf("%d%d", &uu, &xx); printf("%d\n", query(T[L[uu] - 1], T[R[uu]], xx)); } } return 0; }