zoukankan      html  css  js  c++  java
  • [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;
    }
    
  • 相关阅读:
    我的架构经验系列文章 前端架构
    我的架构经验系列文章 后端架构 安全层面
    Adhesive框架系列文章报警服务模块使用和实现
    Adhesive框架系列文章Mongodb数据服务模块实现(上)
    在Silverlight程序中使用Thread一个很容易被忽略的问题
    .net(偏web) vs j2ee的一些框架选型
    Wcf扩展
    Adhesive框架系列文章内存队列服务模块使用和实现
    【翻译】C#编程语言和JAVA编程语言的比较(下)
    在测试Adhesive的时候发现一个Mongodb官方驱动1.1.0.4184比较严重的BUG
  • 原文地址:https://www.cnblogs.com/list1/p/10386946.html
Copyright © 2011-2022 走看看