• 洛谷 P4592 [TJOI2018]异或 解题报告


    P4592 [TJOI2018]异或

    题目描述

    现在有一颗以(1)为根节点的由(n)个节点组成的树,树上每个节点上都有一个权值(v_i)。现在有(Q)次操作,操作如下:

    • 1 x y:查询节点(x)的子树中与(y)异或结果的最大值

    • 2 x y:查询路径(x)(y)上点与(z)异或结果最大值

    输入输出格式

    输入格式:

    第一行是两个数字(n,Q);

    第二行是(n)个数字用空格隔开,第(i)个数字(v_i)表示点(i)上的权值

    接下来(n-1)行,每行两个数,(x,y),表示节点(x)(y)之间有边

    接下来(Q)行,每一行为一个查询,格式如上所述.

    输出格式:

    对于每一个查询,输出一行,表示满足条件的最大值。

    说明

    对于(10\%)的数据,有(1<n,Qleq100)

    对于(20\%)的数据,有(1<n,Qleq1000)

    对于(40\%)的数据,有(1<n,Qleq10000)

    对于(100\%)的数据,有(1<n,Qleq100000)

    对于(100\%)的数据,有查询(1)中的(yleq2^{30}),查询(2)中的(zleq2^{30})


    区间异或最大值可以用可持久化字典树实现。

    这个题建对DFS序建一颗,对自根向下的链建,分别处理两种询问就可以了。


    Code:

    #include <cstdio>
    #include <cctype>
    const int N=1e5+10;
    int read()
    {
        int x=0;char c=getchar();
        while(!isdigit(c)) c=getchar();
        while(isdigit(c)) {x=x*10+c-'0';c=getchar();}
        return x;
    }
    int max(int x,int y){return x>y?x:y;}
    #define ls ch[now][0]
    #define rs ch[now][1]
    #define rep(i,a,b) for(int i=a;i<=b;i++)
    int head[N],to[N<<1],Next[N<<1],cnt;
    void add(int u,int v)
    {
        to[++cnt]=v,Next[cnt]=head[u],head[u]=cnt;
    }
    int poi[N],n,Q;
    namespace work1//子树
    {
        int ch[N*32][2],mx[N*32],tot,dfn[N],low[N],ha[N],dfsclock,root[N];
        void dfs(int now,int fa)
        {
            dfn[now]=++dfsclock;
            ha[dfsclock]=now;
            for(int i=head[now];i;i=Next[i])
                if(to[i]!=fa)
                    dfs(to[i],now);
            low[now]=dfsclock;
        }
        void Insert(int las,int &now,int dep,int id)
        {
            if(!now) now=++tot;
            if(dep<0){mx[now]=id;return;}
            int bit=poi[ha[id]]>>dep&1;
            Insert(ch[las][bit],ch[now][bit],dep-1,id);
            ch[now][bit^1]=ch[las][bit^1];
            mx[now]=max(mx[ls],mx[rs]);
        }
        void init()
        {
            dfs(1,0);
            rep(i,1,n) Insert(root[i-1],root[i],30,i);
        }
        int query(int now,int les,int dep,int x)
        {
            if(dep<0) return x^poi[ha[mx[now]]];
            int bit=x>>dep&1;
            if(mx[ch[now][bit^1]]>=les) return query(ch[now][bit^1],les,dep-1,x);
            return query(ch[now][bit],les,dep-1,x);
        }
        void work()
        {
            int x=read(),y=read();
            printf("%d
    ",query(root[low[x]],dfn[x],30,y));
        }
    }
    namespace work2
    {
        int f[N][20],ch[N*32][2],mx[N*32],root[N],dep[N],en[N*32],tot,tmp;
        void swap(int &x,int &y){tmp=x,x=y,y=tmp;}
        void Insert(int las,int &now,int de,int id)
        {
            if(!now) now=++tot;
            if(de<0){mx[now]=dep[id],en[now]=id;return;}
            int bit=poi[id]>>de&1;
            Insert(ch[las][bit],ch[now][bit],de-1,id);
            ch[now][bit^1]=ch[las][bit^1];
            mx[now]=max(mx[ls],mx[rs]);
        }
        void dfs(int now)
        {
            for(int i=1;f[now][i-1];i++) f[now][i]=f[f[now][i-1]][i-1];
            for(int i=head[now];i;i=Next[i])
            {
                int v=to[i];
                if(v==f[now][0]) continue;
                dep[v]=dep[now]+1;
                f[v][0]=now;
                Insert(root[now],root[v],30,v);
                dfs(v);
            }
        }
        void init()
        {
            dep[1]=1;
            Insert(0,root[1],30,1);
            dfs(1);
        }
        int LCA(int x,int y)
        {
            if(dep[x]<dep[y]) swap(x,y);
            for(int i=18;~i;i--)
                if(dep[f[x][i]]>=dep[y])
                    x=f[x][i];
            if(x==y) return x;
            for(int i=18;~i;i--)
                if(f[x][i]!=f[y][i])
                    x=f[x][i],y=f[y][i];
            return f[x][0];
        }
        int query(int now,int les,int de,int x)
        {
            if(de<0) return poi[en[now]]^x;
            int bit=x>>de&1;
            if(mx[ch[now][bit^1]]>=les) return query(ch[now][bit^1],les,de-1,x);
            return query(ch[now][bit],les,de-1,x);
        }
        void work()
        {
            int x=read(),y=read(),z=read(),lca=LCA(x,y);
            printf("%d
    ",max(query(root[x],dep[lca],30,z),query(root[y],dep[lca],30,z)));
        }
    }
    int main()
    {
        n=read(),Q=read();
        rep(i,1,n) scanf("%d",poi+i);
        for(int u,v,i=1;i<n;i++)
            u=read(),v=read(),add(u,v),add(v,u);
        work1::init();
        work2::init();
        rep(i,1,Q)
        {
            if(read()==1) work1::work();
            else work2::work();
        }
        return 0;
    }
    

    2018.11.3

  • 相关阅读:
    数组中最大和的子数组
    数据结构与算法面试题80道
    fcntl获取和修改文件打开状态标志
    dup等复制文件描述符函数
    截断文件函数truncate和ftruncate
    浅析
    五个Taurus垃圾回收compactor优化方案,减少系统资源占用
    如何用交互式特征工程工具进行数据分析处理
    【华为云技术分享】解密如何使用昇腾AI计算解决方案构建业务引擎
    Scrum Master教你四招,瓦解团队内部刺头
  • 原文地址:https://www.cnblogs.com/butterflydew/p/9899547.html
Copyright © 2020-2023  润新知