[TJOI2018]异或

Description:

现在有一颗以1为根节点的由n个节点组成的树,树上每个节点上都有一个权值v

​现在有Q次操作,操作如下:

1.1 x y :查询节点x的子树中与y异或结果的最大值
2.2 x y z :查询路径x到y上点与z异或结果最大值

Hint:

(n,q<=10^5)

Solution:

水题,按dfs序建主席树解决询问1,树上主席树解决询问2

#include<bits/stdc++.h>
using namespace std;
const int mxm=1e5+5,mxn=5e6+5;
int n,m,cnt,val[mxm],hd[mxm],sz[mxm],id[mxm],dep[mxm],f[mxm][18];

struct ed {
    int to,nxt;
}t[mxm<<1];

inline void add(int u,int v) {
    t[++cnt]=(ed) {v,hd[u]}, hd[u]=cnt;
}

struct Trie {
    int ch[mxn][2],rt[mxn],sum[mxn],tot,dfn;
    void dfs1(int u,int fa) {
        sz[u]=1; id[u]=++dfn; 
        ins(rt[id[u]-1],rt[id[u]],30,val[u]);
        for(int i=hd[u];i;i=t[i].nxt) {
            int v=t[i].to;
            if(v==fa) continue ;
            dfs1(v,u); sz[u]+=sz[v];
        }
    }
    void dfs2(int u,int fa) {
        f[u][0]=fa; dep[u]=dep[fa]+1;
        ins(rt[fa],rt[u],30,val[u]);
        for(int i=hd[u];i;i=t[i].nxt) {
            int v=t[i].to;
            if(v==fa) continue ;
            dfs2(v,u);
        }
    }
    int LCA(int x,int y) {
        if(dep[x]<dep[y]) swap(x,y);
        for(int i=17;i>=0;--i)
            if(dep[f[x][i]]>=dep[y])
                x=f[x][i];
        if(x==y) return x;
        for(int i=17;i>=0;--i) 
            if(f[x][i]!=f[y][i])
                x=f[x][i],y=f[y][i];
        return f[x][0];
    }
    void init() {
        for(int j=1;j<=17;++j) 
            for(int i=1;i<=n;++i) 
                f[i][j]=f[f[i][j-1]][j-1];
    }
    void ins(int pre,int& p,int k,int x) {
        p=++tot; sum[p]=sum[pre]+1; if(k<0) return ;
        int tp=x>>k&1; ch[p][tp^1]=ch[pre][tp^1];
        ins(ch[pre][tp],ch[p][tp],k-1,x);
    };
    int query1(int pre,int p,int k,int x) {
        if(k<0) return 0; int tp=x>>k&1;
        int is=sum[ch[p][tp^1]]-sum[ch[pre][tp^1]];
        if(is) return (1<<k)+query1(ch[pre][tp^1],ch[p][tp^1],k-1,x);
        else return query1(ch[pre][tp],ch[p][tp],k-1,x);
    };
    int query2(int las1,int las2,int p1,int p2,int k,int x) {
        if(k<0) return 0; int tp=x>>k&1;
        int is=sum[ch[p1][tp^1]]+sum[ch[p2][tp^1]]-sum[ch[las1][tp^1]]-sum[ch[las2][tp^1]];
        if(is) return (1<<k)+query2(ch[las1][tp^1],ch[las2][tp^1],ch[p1][tp^1],ch[p2][tp^1],k-1,x);
        else return query2(ch[las1][tp],ch[las2][tp],ch[p1][tp],ch[p2][tp],k-1,x);
    }
}T1,T2;

int main()
{
    scanf("%d%d",&n,&m); int opt,x,y,z,u,v;
    for(int i=1;i<=n;++i) scanf("%d",&val[i]);
    for(int i=1;i<n;++i) {
        scanf("%d%d",&u,&v);
        add(u,v); add(v,u);
    }
    T1.dfs1(1,0),T2.dfs2(1,0),T2.init();
    for(int i=1;i<=m;++i) {
        scanf("%d",&opt);
        if(opt==1) {
            scanf("%d%d",&x,&y);
            printf("%d
",T1.query1(T1.rt[id[x]-1],T1.rt[id[x]+sz[x]-1],30,y));
        }
        else {
            scanf("%d%d%d",&x,&y,&z); int lca=T2.LCA(x,y);
            printf("%d
",T2.query2(T2.rt[f[lca][0]],T2.rt[lca],T2.rt[x],T2.rt[y],30,z));
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/list1/p/10386946.html