• BZOJ2049: [SDOI2008]Cave 洞穴勘测 LCT


    第一道LCT。

    动态维护集合就好了。

    LCT就是一群链通过父亲关系练成一颗不太连续的树,通过儿子关系组成实边,在这里没有查找单点一说,都是直接拎起来,对于一条链他对外界的有用反馈就是他的链父亲以及需求点的真实位置,而每次cut的时候就会把标记下方好,每次spaly都会找到这个点在这条链中的真实位置,因此这个玄妙的东西就形成了。

    null不是一定要用只是简化了你的讨论。

    千万别忘了这里的spaly的特别之处!!!!!!!!

    #include<cstring>
    #include<cstdio>
    #define MAXN 10010
    using namespace std;
    char Cmd[50];
    int n,m;
    struct Node
    {
       Node *f,*ch[2];
       bool rev;
       void pushdown();
    }null[MAXN];
    inline void swap(Node *&x,Node *&y)
    {
       Node *temp=x;
       x=y;
       y=temp; 
    }
    void Node:: pushdown()
    {
       if(!rev)return;
       ch[0]->rev^=1;
       ch[1]->rev^=1;
       swap(ch[0],ch[1]);
       rev=0;
    }
    inline void Init()
    {
       scanf("%d%d",&n,&m);
       null->ch[0]=null->ch[1]=null->f=null;
       for(int i=1;i<=n;i++)
        null[i].ch[0]=null[i].ch[1]=null[i].f=null;
    }
    inline int get(Node *x)
    {
       return x->f->ch[1]==x;
    }
    inline bool isroot(Node *x)
    {
       return x->f->ch[1]!=x&&x->f->ch[0]!=x;
    }
    inline void rotate(Node *x)
    {
       Node *fa=x->f,*pa=fa->f;
       int j=get(x);
       if(!isroot(fa))pa->ch[get(fa)]=x;//important point
       if((fa->ch[j]=x->ch[j^1])!=null)fa->ch[j]->f=fa;//important point
       fa->f=x;
       x->f=pa;
       x->ch[j^1]=fa;
    }
    inline void spaly(Node *x)
    {
       x->pushdown();//important point
       for(Node *fa=x->f;!isroot(x);rotate(x),fa=x->f)
        if(!isroot(fa))
        {
         fa->f->pushdown(),fa->pushdown(),x->pushdown();
         rotate(get(x)==get(fa)?fa:x);
        }
        else
         fa->pushdown(),x->pushdown();
    }
    inline void expose(Node *x)
    {
        Node *y=null;
        while(x!=null)
        {
          spaly(x);
          x->ch[1]=y;
          y=x;
          x=x->f;
        }
    }
    inline void make_root(Node *x)
    {
        expose(x);
        spaly(x);
        x->rev^=1;
    }
    inline Node *get_root(Node *x)
    {
        expose(x);
        spaly(x);
        x->pushdown();
        while(x->ch[0]!=null)
          x=x->ch[0],x->pushdown();
        return x;
    }
    inline void link(Node *x,Node *y)
    {
        make_root(x);
        x->f=y;
    }
    inline void cut(Node *x,Node *y)
    {
        make_root(x);
        expose(y);
        spaly(y);
        y->ch[0]->f=null;
        y->ch[0]=null;
    }
    inline void work()
    {
       while(m--)
       {
         int x,y;
         scanf("%s%d%d",Cmd,&x,&y);
         switch(Cmd[0])
         {
            case 'C':link(null+x,null+y);
                     break;
            case 'D':cut(null+x,null+y);
                     break;
            case 'Q':if(get_root(null+x)==get_root(null+y))
                       printf("Yes
    ");
                     else
                       printf("No
    ");
                     break;
         }
       }
    }
    int main()
    {
       Init();
       work();
       return 0;
    }
  • 相关阅读:
    启用oracle 11g自己主动收集统计信息
    在java中,怎样跳出当前的多重循环?
    从编程的角度理解gradle脚本﹘﹘Android Studio脚本构建和编程[魅族Degao]
    【SpringMVC架构】SpringMVC入门实例,解析工作原理(二)
    实现icon和文字垂直居中的两种方法-(vertical-align and line-height)
    android发送get请求时报错
    KeyEvent 键码值
    Android-黑科技-微信抢红包必备软件
    Delicious Apples (hdu 5303 贪心+枚举)
    vim 插件配置博客记录
  • 原文地址:https://www.cnblogs.com/TSHugh/p/7141219.html
Copyright © 2020-2023  润新知