zoukankan      html  css  js  c++  java
  • HDU 4757 Tree 可持久化字典树 trie

    http://acm.hdu.edu.cn/showproblem.php?pid=4757

    给出一棵树,每个节点有权值,每次查询节点 (u,v) 以及 val,问 u 到 v 路径上的某个节点与 val 异或最大的值是多少。

    和可持久化线段树差不多,看代码吧。

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 #include<cmath>
     5 #include<iostream>
     6 #include<vector>
     7 using namespace std;
     8 #define LL long long
     9 const int maxn=100010;
    10 const int maxm=3000010;
    11 int n,m;
    12 int a[maxn]={},fa[maxn][20]={},dep[maxn]={},rt[maxn]={};
    13 int sig[maxm][2]={},sz[maxm]={},cnt=0;
    14 struct nod{int y,next;}e[maxn*2];int head[maxn],tot=0;
    15 inline void init(int x,int y){e[++tot].y=y;e[tot].next=head[x];head[x]=tot;}
    16 inline int getnew(){
    17     sig[++cnt][0]=0;sig[cnt][1]=0;
    18     sz[cnt]=0;return cnt;
    19 }
    20 inline void bui(int x,int pa,int val){
    21     rt[x]=getnew();pa=rt[pa];
    22     x=rt[x];
    23     for(int i=15;i>=0;--i){
    24         int ch=(val>>i)&1;
    25         if(!sig[x][ch]){
    26             int id=getnew();
    27             sig[x][ch]=id; sig[x][!ch]=sig[pa][!ch];
    28             sz[sig[x][ch]]=sz[sig[pa][ch]];
    29         }
    30         x=sig[x][ch];pa=sig[pa][ch];
    31         ++sz[x];
    32     }
    33 }
    34 void dfs(int x){
    35     bui(x,fa[x][0],a[x]);
    36     for(int i=1;fa[x][i-1];++i)fa[x][i]=fa[fa[x][i-1]][i-1];
    37     for(int i=head[x];i;i=e[i].next){
    38         if(e[i].y==fa[x][0])continue;
    39         fa[e[i].y][0]=x;dep[e[i].y]=dep[x]+1;dfs(e[i].y);
    40     }
    41 }
    42 inline int getlca(int x,int y){
    43     if(dep[x]<dep[y])swap(x,y);
    44     for(int i=19;i>=0;--i)if(dep[fa[x][i]]>=dep[y])x=fa[x][i];
    45     if(x==y)return x;
    46     for(int i=19;i>=0;--i)if(fa[x][i]!=fa[y][i]){x=fa[x][i];y=fa[y][i];}
    47     return fa[x][0];
    48 }
    49 int Query(int x,int y,int val){
    50     int lc=getlca(x,y); int res=a[lc]^val;
    51     x=rt[x];y=rt[y];lc=rt[lc];
    52     int ret=0;
    53     for(int i=15;i>=0;--i){
    54         int ch=(val>>i)&1;
    55         if(sz[sig[x][!ch]]+sz[sig[y][!ch]]-2*sz[sig[lc][!ch]]>0){
    56             ret+=1<<i;
    57             ch=!ch;
    58         }
    59         x=sig[x][ch];y=sig[y][ch];lc=sig[lc][ch];
    60     }
    61     return max(res,ret);
    62 }
    63 int main(){
    64     while(~scanf("%d%d",&n,&m)){
    65         memset(head,0,sizeof(head));memset(rt,0,sizeof(rt));
    66         memset(sig,0,sizeof(sig));memset(fa,0,sizeof(fa));
    67         int x,y,z;tot=0;cnt=0;
    68         for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    69         for(int i=1;i<n;i++){scanf("%d%d",&x,&y);init(x,y);init(y,x);}
    70         dep[1]=1;dfs(1);
    71         for(int i=1;i<=m;i++){
    72             scanf("%d%d%d",&x,&y,&z);
    73             printf("%d
    ",Query(x,y,z));
    74         }
    75     }
    76     return 0;
    77 }
    View Code

  • 相关阅读:
    Java应用开发与实践
    大话存储:存储系统底层架构原理极限剖析(终极版)
    Excel 2016公式与函数应用大全
    Excel高效办公应用技巧
    业务弯路池子
    一个现象,
    为什么有时候 进入这么多次,一次是 38次,一次是 114次,
    恶心 从判断开始,
    but,
    这两个的意思是不同的。。。
  • 原文地址:https://www.cnblogs.com/137shoebills/p/9127081.html
Copyright © 2011-2022 走看看