您的位置:首页 > 其它

HDU6191(dfs序 + 可持久Trie树)

2017-08-31 19:50 239 查看


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;
}



                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: