【HDU 6191】Query on A Tree 【可持久化字典树】

题目

  给出一棵有n个结点的树,树根是1,每个结点给出一个value。然后给出q个询问,每个询问给出两个整数u和x,你要在以u结点为根的子树中找出一个结点v,使得val[v] xor x最大, 并输出这个最大值

分析

  显而易见的可持久化字典树,只不过这次每次查询不是查询一个区间,而是查询一棵子树。那么也很简单,我们只要预处理出dfs序然后找出每个结点以它为根的子树在dfs序中的区间。然后以这个区间建可持久化字典树就可以了。

 

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <iostream>
 4 #include <algorithm>
 5 
 6 using namespace std;
 7 const int maxn=100000+10;
 8 int val[maxn];
 9 int head[maxn],to[maxn],Next[maxn];
10 int n,q,sz;
11 void add_edge(int a,int b){
12     ++sz;
13     to[sz]=b;Next[sz]=head[a];head[a]=sz;
14 }
15 int order[maxn],L[maxn],R[maxn],num;
16 void dfs(int u,int fa){
17     num++;
18     order[num]=val[u];
19     L[u]=num;
20     for(int i=head[u];i!=-1;i=Next[i]){
21         int v=to[i];
22         if(v!=fa)
23             dfs(v,u);
24     }
25     R[u]=num;
26 }
27 int ch[maxn*2*33][2],root[maxn],sum[maxn*2*33][2],cnt,val_t[2*maxn*33];
28 void update(int x,int y,int a,int ID){
29     root[x]=++cnt;x=root[x];
30     for(int i=31;i>=0;i--){
31         int id=(a>>i)&1;
32         sum[x][id]+=sum[y][id]+1;
33         sum[x][!id]+=sum[y][!id];
34         ch[x][!id]=ch[y][!id];
35         ch[x][id]=++cnt;
36         memset(ch[cnt],0,sizeof(ch[cnt]));
37         val_t[cnt]=0;
38         x=ch[x][id];y=ch[y][id];
39     }
40     val_t[x]=ID;
41 }
42 int query(int x,int y,int a){
43     for(int i=31;i>=0;i--){
44         int id=(a>>i)&1;
45         if(sum[x][!id]-sum[y][!id]){
46             x=ch[x][!id],y=ch[y][!id];
47         }else{
48             x=ch[x][id],y=ch[y][id];
49         }
50     }
51     return val_t[x];
52 }
53 int main(){
54     while(scanf("%d%d",&n,&q)!=EOF){
55         sz=0;
56         cnt=0;
57         memset(head,-1,sizeof(head));
58         memset(sum,0,sizeof(sum));
59         for(int i=1;i<=n;i++){
60             scanf("%d",&val[i]);
61         }
62         for(int i=2;i<=n;i++){
63             int a;
64             scanf("%d",&a);
65             add_edge(a,i);
66         }
67         num=0;
68         dfs(1,-1);
69 //        for(int i=1;i<=n;i++)
70 //            printf("%d ",order[i]);
71 //        printf("\n");
72         update(0,0,0,0);
73         for(int i=1;i<=n;i++){
74             update(i,root[i-1],order[i],i);
75         }
76         int u,x;
77         for(int i=1;i<=q;i++){
78             scanf("%d%d",&u,&x);
79             printf("%d\n",order[query(root[R[u]],root[L[u]-1],x)]^x);
80         }
81     }
82 return 0;
83 }
View Code

猜你喜欢

转载自www.cnblogs.com/LQLlulu/p/9496426.html
今日推荐