hdu4757(LCA+可持久化字典树)

来源:互联网 发布:外资企业数据 编辑:程序博客网 时间:2024/05/16 15:16

题目链接:点这里!!!


题意:给你一个n个节点的树(n<=1e5),每个节点都有一个权值a[i](a[i]<=2^16),再给你q(q<=1e5)个询问,问你(x,y)这条路径上的权值与v异或的最大值为多少?


题解:

也是可持久化字典树,只是现在是在树上搞一搞。其实也是一样的,我们把儿子和父亲在可持久化字典树连起来就可以了,求出他们的LCA,然后乱搞就可以了!!!(具体看代码)


代码:

#include<cstdio>#include<cstring>#include<iostream>#include<sstream>#include<algorithm>#include<vector>#include<bitset>#include<set>#include<queue>#include<stack>#include<map>#include<cstdlib>#include<cmath>#define pb push_back#define pa pair<int,int>#define clr(a,b) memset(a,b,sizeof(a))#define lson lr<<1,l,mid#define rson lr<<1|1,mid+1,r#define bug(x) printf("%d++++++++++++++++++++%d\n",x,x)#define key_value ch[ch[root][1]][0]#pragma comment(linker, "/STACK:102400000000,102400000000")typedef  long long LL;const LL  MOD = 1000000007;const int N = 1e5+15;const int maxn = 1e6+15;const int letter = 130;const int INF = 1e9;const double pi=acos(-1.0);const double eps=1e-10;using namespace std;inline int read(){    int x=0,f=1;char ch=getchar();    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}    return x*f;}int n,q,head[N],tot,a[N];int fa[N][18],deep[N],bin[18];int ch[N*18][2],sum[N*18],root[N],cnt;struct edges{    int to,next;}e[N<<1];void addedges(int u,int v){    e[tot].to=v,e[tot].next=head[u],head[u]=tot++;}int trie_insert(int x,int val){    int tmp,y;    tmp=y=++cnt;    for(int i=16;i>=0;i--){        ch[y][0]=ch[x][0],ch[y][1]=ch[x][1];        sum[y]=sum[x]+1;        int t=val&bin[i];        t>>=i;        x=ch[x][t];        ch[y][t]=++cnt;        y=ch[y][t];    }    sum[y]=sum[x]+1;    return tmp;}int trie_query(int x,int y,int z,int val){    int ans=0,ps=a[z];    x=root[x],y=root[y],z=root[z];    for(int i=16;i>=0;i--){        int p=(val>>i)&1;        if(sum[ch[x][p^1]]+sum[ch[y][p^1]]-2*sum[ch[z][p^1]]>0){            x=ch[x][p^1],y=ch[y][p^1],z=ch[z][p^1];            ans|=(1<<i);        }        else x=ch[x][p],y=ch[y][p],z=ch[z][p];    }    return max(ans,val^ps);}void dfs(int x,int g){    root[x]=trie_insert(root[g],a[x]);    for(int i=head[x];i!=-1;i=e[i].next){        int to=e[i].to;        if(to==g) continue;        fa[to][0]=x;        deep[to]=deep[x]+1;        dfs(to,x);    }}int lca(int x,int y){    if(deep[x]<deep[y]) swap(x,y);    int t=deep[x]-deep[y];    for(int i=16;i>=0;i--) if(t&bin[i])x=fa[x][i];    for(int i=16;i>=0;i--)        if(fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i];    if(x==y) return x;    return fa[x][0];}void init(){    tot=cnt=0;    clr(head,-1);    deep[1]=0;    clr(sum,0),clr(ch,0),clr(root,0),clr(fa,0);}int main(){    int x,y,z,v;    bin[0]=1;    for(int i=1;i<=16;i++) bin[i]=bin[i-1]<<1;    while(~scanf("%d%d",&n,&q)){        init();        for(int i=1;i<=n;i++) scanf("%d",a+i);        for(int i=1;i<n;i++){            scanf("%d%d",&x,&y);            addedges(x,y),addedges(y,x);        }        fa[1][0]=0;        dfs(1,0);        for(int j=1;j<=16;j++)            for(int i=1;i<=n;i++)                fa[i][j]=fa[fa[i][j-1]][j-1];        while(q--){            scanf("%d%d%d",&x,&y,&v);            z=lca(x,y);            printf("%d\n",trie_query(x,y,z,v));        }    }    return 0;}


0 0
原创粉丝点击