• [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;
    }
    
  • 相关阅读:
    [Noip2010]乌龟棋
    vijos次小生成树
    hdu3579-Hello Kiki-(扩展欧几里得定理+中国剩余定理)
    hdu1573-X问题-(扩展欧几里得定理+中国剩余定理)
    poj2115-Looooops-(扩展欧几里得定理)
    hdu2669-Romantic-(扩展欧几里得定理)
    poj1061-青蛙的约会-(贝祖定理+扩展欧几里得定理+同余定理)
    hdu1576-A/B-(同余定理+乘法逆元+费马小定理+快速幂)
    hdu4497-GCD and LCM-(欧拉筛+唯一分解定理+组合数)
    hdu3189-Just Do It-(埃氏筛+唯一分解定理)
  • 原文地址:https://www.cnblogs.com/list1/p/10386946.html
Copyright © 2020-2023  润新知