hdu4757 可持续化01字典树+LCA

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

题意:给一棵树,每个节点有权值。每次询问要求回答一个值XOR某条路径上的一个点的最大值。

分析:我们在学可持续化01字典树时,写的模板题是支持区间查询的,插入一个数是pre是和u-1之间建立,那么在树上这个关系就是父亲与儿子的关系建立可持续化01字典树;

   然后查询久查询[fa[lca[x,y]],x]和[fa[lca[x,y]],y]这俩个区间;

hdu4757  可持续化01字典树+LCA
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<vector>
using namespace std;
const int M=1e5+5;
#define pb push_back
struct TRIE{
    int trie[M*32][2],sum[M*32],val[M*32];
    int rt[M*32],tot;
    void init(){
        tot=0;

        memset(trie,0,sizeof(trie));
        memset(sum,0,sizeof(sum));
        memset(val,0,sizeof(val));
        memset(rt,0,sizeof(rt));
        rt[0]=++tot;
    }
    void Insert(int pre,int now,int x){

        for(int i=18;i>=0;i--){
            int id=(x>>i)&1;

            trie[now][id]=++tot;
            trie[now][id^1]=trie[pre][id^1];
            now=trie[now][id];
            pre=trie[pre][id];
            sum[now]=sum[pre]+1;
        }
        val[now]=x;
    }
    int query(int l,int r,int x){
        for(int i=18;i>=0;i--){
            int id=(x>>i)&1;
            if(sum[trie[r][id^1]]-sum[trie[l][id^1]]>0)
                r=trie[r][id^1],l=trie[l][id^1];
            else
                r=trie[r][id],l=trie[l][id];
        }
        return val[r]^x;
    }
}Trie;
int p[M],grand[M][20],s,n,m,root,deep[M];
vector<int>g[M];
void dfs(int u,int fa){
    Trie.rt[u]=++Trie.tot;
    Trie.Insert(Trie.rt[fa],Trie.rt[u],p[u]);
    deep[u]=deep[fa]+1;
    grand[u][0]=fa;
    for(int i=1;i<=s;i++){
        grand[u][i]=grand[grand[u][i-1]][i-1];
        if(!grand[u][i])
            break;
    }
    for(auto v:g[u]){
        if(v!=fa)
            dfs(v,u);
    }
}
void init(){
    s=floor(log(1.0*n)/log(2.0));
    deep[0]=0;
    dfs(root,0);
}
int LCA(int u,int v){
    int a=u,b=v;
    if(deep[a]>deep[b])
        swap(a,b) ;
    for(int i=s;i>=0;i--){
        if(deep[b]>deep[a]&&deep[a]<=deep[grand[b][i]])
            b=grand[b][i];
    }

    for(int i=s;i>=0;i--){
        if(grand[b][i]!=grand[a][i])
            a=grand[a][i],b=grand[b][i];
    }
    if(a!=b)
        a=grand[a][0],b=grand[b][0];
    return a;
}

int main(){
    while(scanf("%d%d",&n,&m)!=EOF){
        Trie.init();
        for(int i=0;i<=n;i++)
            g[i].clear();
        memset(grand,0,sizeof(grand));
        for(int i=1;i<=n;i++)
            scanf("%d",&p[i]);
        for(int u,v,i=1;i<n;i++){
            scanf("%d%d",&u,&v);
            g[u].pb(v);
            g[v].pb(u);
        }
        root=1;
        init();
        while(m--){
            int u,v,x;
            scanf("%d%d%d",&u,&v,&x);
            int lca=LCA(u,v);
            int fa=grand[lca][0];
            printf("%d
",max(Trie.query(Trie.rt[fa],Trie.rt[u],x),Trie.query(Trie.rt[fa],Trie.rt[v],x)));
        }
    }
    return 0;
}
View Code