首页 > 代码库 > HDU4757 Tree(可持久化Trie)

HDU4757 Tree(可持久化Trie)

写过可持久化线段树,但是从来没写过可持久化的Trie,今天补一补。

题目就是典型的给你一个数x,和一个数集,问x和里面的某个数xor起来的最大值是多少。

最原始的是数集是固定的,只需要对数集按照高到低位去建Trie,然后贪心匹配就可以了。

这里则是对树上路径的操作,其实也是一样的,对每个节点x维护root到x的Trie,然后纪录下往左走往右走的叶子节点个数,设z=lca(x,y),那么到了个某个节点能否往某个儿子走的限制条件是 sz[ch[x][c]]+sz[ch[y][c]]-2*sz[ch[z][c]]>0,这样说明下面是存在c的儿子的,接着往下走即可。当然这样算其实是会漏掉lca的,所以最后还要和lca取最大值。

区间的询问作为这题的特例同理也是可以处理的。

#include <iostream>#include <cstdio>#include <cstring>#include <string>#include <algorithm>#include <cmath>#include <queue>#include <cassert>#include <vector>#include <set>using namespace std;#define maxn 120000#define maxnode 2200000#define maxlogv 16vector<int> G[maxn];int n,m;int a[maxn];int f[maxlogv+2][maxn];int dep[maxn];int ch[maxnode][2];int sz[maxnode];int tot;int root[maxn];int newnode(){    memset(ch[tot],0,sizeof(ch[tot]));    sz[tot]=0;    return tot++;}// insert val for x with father as yvoid insert(int x,int y,int val){    x=root[x];y=root[y];    for(int i=15;i>=0;--i){        int c=(val>>i)&1;        if(!ch[x][c]){            int id=newnode();            ch[x][c]=id;            ch[x][!c]=ch[y][!c];            sz[ch[x][c]]=sz[ch[y][c]];        }        x=ch[x][c],y=ch[y][c];        ++sz[x];    }}void dfs(int u,int fa){    f[0][u]=fa;dep[u]=dep[fa]+1;    root[u]=newnode();    insert(u,fa,a[u]);    for(int i=0;i<G[u].size();++i){        int v=G[u][i];        if(v==fa) continue;        dfs(v,u);    }}int lca(int u,int v){    if(dep[u]>dep[v]) swap(u,v);    for(int k=0;k<maxlogv;++k){        if( (dep[v]-dep[u])>>k&1){            v=f[k][v];        }    }    if(u==v) return u;    for(int k=maxlogv-1;k>=0;--k){        if(f[k][u]!=f[k][v]){            u=f[k][u];            v=f[k][v];        }    }    return f[0][u];}int query(int x,int y,int val){    int z=lca(x,y);int res=a[z]^val;    x=root[x],y=root[y],z=root[z];    int ret=0;    for(int i=15;i>=0;--i){        int c=(val>>i)&1;        if(sz[ch[x][!c]]+sz[ch[y][!c]]-2*sz[ch[z][!c]]>0){            ret+=1<<i;            c=!c;        }        x=ch[x][c];        y=ch[y][c];        z=ch[z][c];    }    return max(ret,res);}int main(){    while(cin>>n>>m){        for(int i=1;i<=n;++i){            scanf("%d",a+i);            G[i].clear();        }        int ui,vi;        for(int i=0;i<n-1;++i){            scanf("%d%d",&ui,&vi);            G[ui].push_back(vi);            G[vi].push_back(ui);        }        memset(root,0,sizeof(root));        tot=1;        memset(f,0,sizeof(f));        memset(sz,0,sizeof(sz));        dep[0]=0;        dfs(1,0);        for(int k=0;k+1<maxlogv;++k){            for(int v=1;v<=n;++v){                if(f[k][v]==0) f[k+1][v]=0;                else f[k+1][v]=f[k][f[k][v]];            }        }        int xi,yi,zi;        for(int i=0;i<m;++i){            scanf("%d%d%d",&xi,&yi,&zi);            printf("%d\n",query(xi,yi,zi));        }    }    return 0;}

 

HDU4757 Tree(可持久化Trie)