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?
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
2017ACM/ICPC广西邀请赛-重现赛(感谢广西大学)
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;
}