zoukankan      html  css  js  c++  java
  • TJOI2018 异或

    题目链接:戳我

    可持久化01trie+树链剖分

    其实序列上的大家应该都会做,这个题还不过是把序列上的放到了树上而已。多来一个树剖就可以解决。

    dummyummy说可以不用树剖写。。可是我还是不怎么会。。。等他写完了我再放那种解法的吧。。。

    代码如下:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #define MAXN 200010
    using namespace std;
    int n,m,t,dfn,tot;
    int head[MAXN<<1],wt[MAXN],rt[MAXN],ch[MAXN*32][2],cnt[MAXN*32];
    int siz[MAXN],id[MAXN],w[MAXN],fa[MAXN],son[MAXN],top[MAXN],dep[MAXN];
    struct Edge{int nxt,to;}edge[MAXN<<1];
    inline void add(int from,int to)
    {
        edge[++t].nxt=head[from],edge[t].to=to,head[from]=t;
        edge[++t].nxt=head[to],edge[t].to=from,head[to]=t;
    }
    inline void dfs1(int x,int pre)
    {
        siz[x]=1;
        fa[x]=pre;
        dep[x]=dep[pre]+1;
        int maxx=-1;
        for(int i=head[x];i;i=edge[i].nxt)
        {
            int v=edge[i].to;
            if(v==pre) continue;
            dfs1(v,x);
            siz[x]+=siz[v];
            if(siz[v]>maxx) maxx=siz[v],son[x]=v;
        }
    }
    inline void dfs2(int x,int topf)
    {
        top[x]=topf;
        id[x]=++dfn;
        w[dfn]=wt[x];
        if(son[x]) dfs2(son[x],topf);
        for(int i=head[x];i;i=edge[i].nxt)
        {
            int v=edge[i].to;
            if(v==fa[x]||v==son[x]) continue;
            dfs2(v,v);
        }
    }
    inline void insert(int x,int f,int sum)
    {
        for(int i=31;i>=0;i--)
        {
            int v=((sum>>i)&1);
            ch[x][!v]=ch[f][!v];
            ch[x][v]=++tot;
            cnt[ch[x][v]]=cnt[ch[f][v]]+1;
            x=ch[x][v],f=ch[f][v];
        }
    }
    inline int query(int f,int x,int sum)
    {
        int cur_ans=0;
        for(int i=31;i>=0;i--)
        {
            int v=((sum>>i)&1);
            if(cnt[ch[x][!v]]>cnt[ch[f][!v]])
            {
                cur_ans+=(1<<i);
                x=ch[x][!v],f=ch[f][!v];
            }
            else x=ch[x][v],f=ch[f][v];
        }
        return cur_ans;
    }
    inline int solve(int x,int y,int z)
    {
        int cur_ans=0;
        while(top[x]!=top[y])
        {
            if(dep[top[x]]<dep[top[y]]) swap(x,y);
            cur_ans=max(cur_ans,query(rt[id[top[x]]-1],rt[id[x]],z));
            x=fa[top[x]];
        }
        if(dep[x]>dep[y]) swap(x,y);
        cur_ans=max(cur_ans,query(rt[id[x]-1],rt[id[y]],z));
        return cur_ans;
    }
    int main()
    {
        #ifndef ONLINE_JUDGE
        freopen("ce.in","r",stdin);
        #endif
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++) scanf("%d",&wt[i]);
        for(int i=1;i<n;i++)
        {
            int u,v;
            scanf("%d%d",&u,&v);
            add(u,v);
        }
        dfs1(1,0);
        dfs2(1,1);
        rt[0]=++tot;
        insert(rt[0],0,0);
        //for(int i=1;i<=n;i++) printf("i=%d fa=%d w=%d
    ",i,fa[i],w[i]);
        //for(int i=1;i<=n;i++) printf("i=%d id=%d siz=%d
    ",i,id[i],siz[i]);
        for(int i=1;i<=n;i++) rt[i]=++tot,insert(rt[i],rt[i-1],w[i]);
        //for(int i=1;i<=n;i++) printf("rt[%d]=%d
    ",i,rt[i]);
        for(int i=1;i<=m;i++)
        {
            int op,x,y,z;
            scanf("%d",&op);
            if(op==1)
            {
                scanf("%d%d",&x,&y);
                //printf("op=%d x=%d y=%d
    ",op,x,y);
                printf("%d
    ",query(rt[id[x]-1],rt[id[x]+siz[x]-1],y));
            }
            else
            {
                scanf("%d%d%d",&x,&y,&z);
                //printf("op=%d x=%d y=%d z=%d
    ",op,x,y,z);
                printf("%d
    ",solve(x,y,z));
            }
        }
        return 0;
    }
    
  • 相关阅读:
    linux下音乐播放软件
    老男孩教育Python自动化开发精英班-开班典礼感想
    【热身】github的使用
    ubuntu12.04下有线网无电缆插入问题
    ubuntu12.04下安装搜狗拼音
    对树莓派学习开发环境的探讨
    Ubuntu12.04下安装VirtualBox
    ubuntu下安装显卡驱动
    ubuntu下使用锐捷校园网
    深度学习之优化算法
  • 原文地址:https://www.cnblogs.com/fengxunling/p/10485657.html
Copyright © 2011-2022 走看看