HDU 4757 可持久化字典树(Trie)

【题目大意】

    一颗无根树,每个节点有权值,每次提问x,y,z,回答节点x到y的唯一路径上xor z的最大值。

【分析】

    Trie保存每个2进制位,然后类似贪心的遍历一次即可,遍历的时候,用x,y,lca,falca的各个版本来维护是否有串即可。


【代码】

/***********************
    ID:Ciocio
    LANG:C++
    DATE:2014-1-23
    TASK:Tree
***********************/
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <queue>

using namespace std;

#define MAXN 100005
#define MAXQ 100005

struct Tree{
    Tree* lc;
    int sz;
    Tree* rc;
};
Tree Pool[50*MAXN];
Tree* New;
Tree* P[MAXN];
int N,Q,logn;
int Last[MAXN],Next[MAXN<<1],Y[MAXN<<1];
int val[MAXN],Dep[MAXN],Fa[MAXN*2][20];

void _read(int &x){
    char tt=getchar();
    while(tt<'0'||'9'<tt) tt=getchar();
    for(x=0;'0'<=tt&&tt<='9';x=(x<<1)+(x<<3)+tt-'0',tt=getchar());
}

int totM;
void _addedge(int u,int v){
    Y[++totM]=v;Next[totM]=Last[u];
    Last[u]=totM;
}

void _init(){
    for(int i=1;i<=N;i++) _read(val[i]);
    int u,v;
    for(int i=1;i<N;i++){
        _read(u);_read(v);
        _addedge(u,v);
        _addedge(v,u);
    }
}

Tree* null;
Tree* Get(Tree* lc,int sz,Tree* rc){
    New->lc=lc;
    New->sz=sz;
    New->rc=rc;
    return New++;
}

Tree* Insert(Tree* T,int num,int i){
    if(i==-1) return Get(null,T->sz+1,null);
    if((num>>i)&1)
        return Get(Insert(T->lc,num,i-1),T->sz+1,T->rc);
    else
        return Get(T->lc,T->sz+1,Insert(T->rc,num,i-1));
}

void _Dfs(int u,int fa){
    Fa[u][0]=fa;
    P[u]=Insert(P[fa],val[u],15);
    for(int j=Last[u];j;j=Next[j]){
        int v=Y[j];
        if(v!=fa) _Dfs(v,u);
    }
}

void _pre_lca(int x){
    Dep[x]=Dep[Fa[x][0]]+1;
    for(int i=1;i<=15;i++) Fa[x][i]=Fa[Fa[x][i-1]][i-1];
    for(int j=Last[x];j;j=Next[j])
        if(Y[j]!=Fa[x][0])
            _pre_lca(Y[j]);
}

int _Lca(int x,int y){
    if(Dep[x]<Dep[y]) swap(x,y);
    int k=Dep[x]-Dep[y];
    for(int i=0;i<=logn;i++)
        if((k>>i)&1)
            x=Fa[x][i];
    if(x==y) return x;
    k=ceil(log2(Dep[x]));
    for(int i=k;i>=0;i--)
        if(Fa[x][i]!=Fa[y][i]){
            x=Fa[x][i];
            y=Fa[y][i];
        }
    return Fa[x][0];
}

int Search(Tree* x,Tree* y,Tree* flca,Tree* lca,int key,int i){
    if(i==-1) return 0;
    int lc_sz=x->lc->sz+y->lc->sz-flca->lc->sz-lca->lc->sz;
    int rc_sz=x->rc->sz+y->rc->sz-flca->rc->sz-lca->rc->sz;
    int tmp=((key>>i)&1);
    if(tmp==0){
        if(lc_sz!=0) return (1<<i)+Search(x->lc,y->lc,flca->lc,lca->lc,key,i-1);
        return Search(x->rc,y->rc,flca->rc,lca->rc,key,i-1);
    }
    else{
        if(rc_sz!=0) return (1<<i)+Search(x->rc,y->rc,flca->rc,lca->rc,key,i-1);
        return Search(x->lc,y->lc,flca->lc,lca->lc,key,i-1);
    }
}

void _solve(){
    _Dfs(1,0);
    _pre_lca(1);
    int x,y,z,lca;
    while(Q--){
        _read(x);_read(y);_read(z);
        lca=_Lca(x,y);
        printf("%d\n",Search(P[x],P[y],P[Fa[lca][0]],P[lca],z,15));
    }
}

int main(){
    while(scanf("%d%d",&N,&Q)!=EOF){
        logn=ceil(log2(N));
        memset(Last,0,sizeof Last);
        memset(Pool,0,sizeof Pool);
        memset(P,0,sizeof P);
        totM=0;
        New=Pool;
        null=Get(0,0,0);
        null->lc=null;
        null->rc=null;
        P[0]=null;
        _init();
        _solve();
    }
    return 0;
}

    

    原文作者:Trie树
    原文地址: https://blog.csdn.net/greatwjj/article/details/18733185
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞