zoukankan      html  css  js  c++  java
  • 【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("
    ");
    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
    ",order[query(root[R[u]],root[L[u]-1],x)]^x);
    80         }
    81     }
    82 return 0;
    83 }
    View Code
  • 相关阅读:
    临界区,互斥量,信号量,事件的区别
    解决位图失真-SetStretchBltMode()
    Invalidate、RedrawWindow与UpdateWindow
    Shlwapi.h Shlwapi.dll 动态库
    C++ _access和_waccess的使用方法
    纯C++ 连接SQL Server2005 数据库读写操作的小例子
    测试代码执行时间的帮助类
    BUG: GetDC() ReleaseDC()引起的内存泄漏
    DebugView图文教程
    CreateFile函数详解
  • 原文地址:https://www.cnblogs.com/LQLlulu/p/9496426.html
Copyright © 2011-2022 走看看