HDU - 4757 Tree (可持久化字典树)

Tree

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 102400/102400 K (Java/Others)
Total Submission(s): 2811    Accepted Submission(s): 812


Problem Description
  Zero and One are good friends who always have fun with each other. This time, they decide to do something on a tree which is a kind of graph that there is only one path from node to node. First, Zero will give One an tree and every node in this tree has a value. Then, Zero will ask One a series of queries. Each query contains three parameters: x, y, z which mean that he want to know the maximum value produced by z xor each value on the path from node x to node y (include node x, node y). Unfortunately, One has no idea in this question. So he need you to solve it.
 

Input
  There are several test cases and the cases end with EOF. For each case:

  The first line contains two integers n(1<=n<=10^5) and m(1<=m<=10^5), which are the amount of tree’s nodes and queries, respectively.

  The second line contains n integers a[1..n] and a[i](0<=a[i]<2^{16}) is the value on the ith node.

  The next n–1 lines contains two integers u v, which means there is an connection between u and v.

  The next m lines contains three integers x y z, which are the parameters of Zero’s query.
 

Output
  For each query, output the answer.
 

Sample Input
 
  
3 21 2 21 22 31 3 12 3 2
 

Sample Output
 
  
30
 

Source
 

Recommend
liuyiding
 



解题思路:深搜一遍树,按照深搜顺序把每一个节点都插入01字典树,当然要可持久化的插入。然后对于每一次查询,实际上就是查询  root[u]+root[v]-2*root[LCA(u,v)] 这个版本的字典树的字典树,root 为不同节点对应的版本。当然这么算会漏了单独lca 节点的,这个单独判断即可。本题用来保存模板。


#include <bits/stdc++.h>
using namespace std;
typedef long long int ll;
 
 
const int MAXN=120005;
const int MAXLOGV=16;
vector<int> G[MAXN];
 
 
int N,M;

 
 
/****LCA****/
int f[MAXLOGV+2][MAXN];
int dep[MAXN];
void dfs(int u,int fa)
{
    f[0][u]=fa;dep[u]=dep[fa]+1;
    for(int i=0;i<G[u].size();++i){
        int v=G[u][i];
        if(v==fa) continue;
        dfs(v,u);
    }
}
void lca_init(){
    memset(f,0,sizeof(f));
    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 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];
}
/****LCA****/
 
 
 
 
int root=1;
int a[MAXN];
int ch[MAXN*40][2];
int num[MAXN*40*2];
int tot=0;
int rt[MAXN];
 
 
 
 
void insert(int x,int r,int lr){
    bitset<21> s(x);
    int cur=r;
    int lcur=lr;
    for(int i=20;i>=0;i--){
        if(!ch[cur][s[i]]){
            ch[cur][s[i]]=++tot;
            ch[cur][!s[i]]=ch[lcur][!s[i]];
            num[ch[cur][s[i]]]=num[ch[lcur][s[i]]];
        }
        cur=ch[cur][s[i]];
        lcur=ch[lcur][s[i]];
        num[cur]++;
    }
}
 
 
ll search(int u,int v,int lca,int x){
    bitset<21> s(x);
    bitset<21> ans;
    unsigned long long res=x^a[lca];
    int ucur=rt[u];
    int vcur=rt[v];
    int lcur=rt[lca];
    for(int i=20;i>=0;i--){
        if((num[ch[ucur][!s[i]]]+num[ch[vcur][!s[i]]]-2*num[ch[lcur][!s[i]]])>0){
            ans[i]=1;
            ucur=ch[ucur][!s[i]];
            vcur=ch[vcur][!s[i]];
            lcur=ch[lcur][!s[i]];
        }
        else{
            ucur=ch[ucur][s[i]];
            vcur=ch[vcur][s[i]];
            lcur=ch[lcur][s[i]];
        }
    }
    return max(ans.to_ullong(),res);
}
 
 
 
 
void insertdfs(int u,int fa){
    rt[u]=++tot;
    insert(a[u],rt[u],rt[fa]);
    for(int i=0;i<G[u].size();i++){
        int v=G[u][i];
        if(v!=fa)
            insertdfs(v,u);
    }
}
 
 
int main(){
 
 
    while(~scanf("%d%d",&N,&M)){
        tot=0;
        memset(ch,0,sizeof(ch));
        memset(num,0,sizeof(num));
        memset(rt,0,sizeof(rt));
        for(int i=1;i<=N;i++){
            scanf("%d",&a[i]);
            G[i].clear();
        }
        int u,v;
        for(int i=0;i<N-1;i++){
            scanf("%d%d",&u,&v);
            G[u].push_back(v);
            G[v].push_back(u);
        }
        lca_init();
        insertdfs(root,0);
        int x;
        while(M--){
            scanf("%d%d%d",&u,&v,&x);
            cout<<search(u,v,LCA(u,v),x)<<endl;
        }
    }
    return 0;
}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

 
 
 

猜你喜欢

转载自blog.csdn.net/lzc504603913/article/details/80230360
今日推荐