• bzoj3319: 黑白树


    Description

    给定一棵树,边的颜色为黑或白,初始时全部为白色。维护两个操作:
    1.查询u到根路径上的第一条黑色边的标号。
    2.将u到v    路径上的所有边的颜色设为黑色。
    Notice:这棵树的根节点为1

    Input

    第一行两个数n,m分别表示点数和操作数。
    接下来n-?    1行,每行2个数u,v.表示一条u到v的边。
    接下来m行,每行为以下格式:
    1 v 表示第一个操作
    2 v u 表示第二种操作

    Output

    对于每个询问,输出相应答案。如果不存在,输出0。

    由于边只会由白变黑,所以总的边修改次数为O(n),用并查集维护每个点到根的路径上最深的白边位置,预处理出边的染色顺序

    逆序处理操作,用并查集维护,一开始把所有点合并到到根路径上第一条黑边,每取消一次染色就把边的下侧节点合并到上侧

    #include<cstdio>
    const int N=1000010,R=50000000;
    char buf[R+4],*ptr=buf-1;
    inline int _int(){
        int x=0,c=*++ptr;
        while(c<48)c=*++ptr;
        while(c>47)x=x*10+c-48,c=*++ptr;
        return x;
    }
    int stk[16],stp=0;
    inline void int_(int x){
        if(!x)stk[++stp]=0;
        while(x)stk[++stp]=x%10,x/=10;
        while(stp)putchar(stk[stp--]+48);
        putchar(10);
    }
    int n,m;
    bool ed[N];
    int f[N],q[N],ql,qr,dep[N],fa[N],id[N],aid[N];
    int et[N*2],enx[N*2],e0[N],eid[N*2],ep=2;
    int qs[N*2],qw[N*2],qp=0,as[N],ap=0;
    inline int get(int x){
        int a=x,c;
        while(x!=f[x])x=f[x];
        while(x!=(c=f[a]))f[a]=x,a=c;
        return x;
    }
    int main(){
        fread(buf,1,R,stdin);
        n=_int();m=_int();
        for(int i=1;i<=n;i++)f[i]=i;
        for(int i=1;i<n;i++){
            int a=_int(),b=_int();
            et[ep]=b;enx[ep]=e0[a];eid[ep]=i;e0[a]=ep++;
            et[ep]=a;enx[ep]=e0[b];eid[ep]=i;e0[b]=ep++;
        }
        ql=qr=0;
        q[qr++]=1;
        dep[1]=1;
        while(ql!=qr){
            int w=q[ql++];
            for(int i=e0[w];i;i=enx[i])if(int u=et[i]){
                et[i^1]=0;
                fa[u]=w;
                id[u]=eid[i];
                dep[q[qr++]=u]=dep[w]+1;
            }
        }
        for(int i=0;i<m;i++)if(_int()==1){
            qs[qp]=1;qw[qp++]=_int();
        }else{
            int a=get(_int()),b=get(_int());
            while(a!=b){
                if(dep[a]<dep[b]){int t=a;a=b;b=t;}
                qw[qp++]=a;
                aid[a]=id[a];
                ed[a]=1;
                a=f[a]=get(fa[a]);
            }
        }
        for(int i=1;i<=n;i++)f[i]=i;
        ql=qr=0;
        q[qr++]=1;
        while(ql!=qr){
            int w=q[ql++];
            for(int i=e0[w];i;i=enx[i])if(int u=et[i]){
                if(ed[w]&&!ed[u])ed[u]=1,f[get(u)]=get(w);
                q[qr++]=u;
            }
        }
        for(int i=qp-1;~i;i--)
            if(qs[i])as[ap++]=aid[get(qw[i])];
            else f[get(qw[i])]=get(fa[qw[i]]);
        while(ap)int_(as[--ap]);
        return 0;
    }
  • 相关阅读:
    【转】Skynet之消息队列
    [转]Skynet之斗转星移
    [转]skynet Lua中的协程
    win7 + nginx + php
    LexAndYacc 安装程序
    ubuntu + samba 共享失败
    [转]TDD之Dummy Stub Fake Mock
    【转】 纯技术帖:MMOG网络同步算法揭秘
    [转]帧锁定同步算法
    [转]游戏中的同步
  • 原文地址:https://www.cnblogs.com/ccz181078/p/5646753.html
Copyright © 2020-2023  润新知