• UOJ #207. 共价大爷游长沙 随机化+LCT维护子树信息


    注意:$LCT$ 在 $link$ 的时候必须要 makeroot.  

    假如要将 $y$ 连到 $x$ 上: 

    如果只是将 $y$ Access 并 splay 然后直接连到 $x$ 上的话你会发现 $y$ 在 $splay$ 中所有左儿子其实都在 $(x,y)$ 之间,而这显然就不对了. 

    code: 

    #include <cstdio>  
    #include <string>
    #include <cstdlib> 
    #include <ctime>
    #include <algorithm>       
    #define N 400006 
    
    using namespace std;                                                    
    
    namespace IO { 
        void setIO(string s) 
        {
            string in=s+".in"; 
            string out=s+".out"; 
            freopen(in.c_str(),"r",stdin); 
            freopen(out.c_str(),"w",stdout); 
        }                  
    };                
    
    namespace LCT { 
    
        #define lson t[x].ch[0] 
        #define rson t[x].ch[1]  
        #define get(x) (t[t[x].f].ch[1]==x) 
        #define IsR(x) (!(t[t[x].f].ch[0]==x||t[t[x].f].ch[1]==x))    
    
        struct node { 
            int sum,son,ch[2],rev,f;    
        }t[N];      
        int sta[N]; 
    
        inline void Pushup(int x) 
        {    
            t[x].sum=t[lson].sum^t[rson].sum^t[x].son;        
        }    
    
        inline void Mark(int x) 
        {
            t[x].rev^=1; 
            swap(lson,rson); 
        }  
    
        inline void Pushdown(int x) 
        { 
            if(t[x].rev) 
            { 
                t[x].rev^=1; 
                if(lson) Mark(lson); 
                if(rson) Mark(rson); 
            }
        } 
    
        inline void Rotate(int x) 
        {
            int old=t[x].f,fold=t[old].f,which=get(x); 
            if(!IsR(old)) t[fold].ch[t[fold].ch[1]==old]=x;   
            t[old].ch[which]=t[x].ch[which^1],t[t[old].ch[which]].f=old; 
            t[x].ch[which^1]=old,t[old].f=x,t[x].f=fold; 
            Pushup(old),Pushup(x); 
        }
    
        inline void Splay(int x) 
        { 
            int v=0,u=x,fa; 
            for(sta[++v]=u;!IsR(u);u=t[u].f)  sta[++v]=t[u].f;   
            for(;v;--v)  Pushdown(sta[v]);   
            for(u=t[u].f;(fa=t[x].f)!=u;Rotate(x)) 
                if(t[fa].f!=u)  
                    Rotate(get(fa)==get(x)?fa:x);   
        }  
    
        void Access(int x) 
        { 
            for(int y=0;x;y=x,x=t[x].f) 
            {
                Splay(x);              
                t[x].son^=t[rson].sum;           
                t[x].son^=t[y].sum;            
                rson=y; 
                Pushup(x); 
            }
        } 
    
        void Move_Root(int x) 
        {    
            Access(x);      
            Splay(x); 
            Mark(x); 
        }     
    
        int Find(int x) 
        { 
            Access(x); 
            while(lson)  x=lson; 
            return x; 
        } 
    
        void Link_Edge(int x,int y) 
        {     
            Move_Root(x); 
            Move_Root(y);    
            t[y].f=x;   
            t[x].son^=t[y].sum;     
            Pushup(x);   
        } 
    
        void Cut_Edge(int x,int y) 
        {               
            Move_Root(x);  
            Access(y),Splay(y);    
            t[t[y].ch[0]].f=0; 
            t[y].ch[0]=0;      
            Pushup(y);        
        }  
    
        void Update(int x,int v) 
        { 
            Access(x);                
            Splay(x);   
            t[x].son^=v;          
            Pushup(x);   
        }  
    
        int query(int x,int y) 
        { 
            Move_Root(x);   
            Access(y);               
            return t[y].son;   
        } 
    
        #undef lson 
        #undef rson 
    
    }; 
    
    struct SS { 
        int x,y,w;   
        SS(int x=0,int y=0,int w=0):x(x),y(y),w(w){}  
    }S[N];  
    
    int n;  
    
    int main() 
    { 
        srand(20011011);
        // IO::setIO("input");  
        int i,j,m,tot=0,su=0;   
        scanf("%d%d%d",&i,&n,&m); 
        for(i=1;i<n;++i) 
        {
            int x,y; 
            scanf("%d%d",&x,&y);                
            LCT::Link_Edge(x,y);           
        }    
        for(i=1;i<=m;++i) 
        {
            int op; 
            scanf("%d",&op);        
            if(op==1) 
            {   
                int x,y,u,v; 
                scanf("%d%d%d%d",&x,&y,&u,&v);  
                LCT::Cut_Edge(x,y); 
                LCT::Link_Edge(u,v);        
            }    
            if(op==2) 
            {     
                int x,y,w; 
                scanf("%d%d",&x,&y);  
                w=rand();   
                S[++tot]=SS(x,y,w);         
                LCT::Update(x,w);    
                LCT::Update(y,w);   
                su^=w; 
            } 
            if(op==3) 
            {    
                int x; 
                scanf("%d",&x);        
                LCT::Update(S[x].x,S[x].w);   
                LCT::Update(S[x].y,S[x].w);    
                su^=S[x].w;   
            } 
            if(op==4) 
            {    
                int x,y; 
                scanf("%d%d",&x,&y);     
                printf("%s
    ",LCT::query(x,y)==su?"YES":"NO");       
            }
        }
        return 0; 
    }
    

      

  • 相关阅读:
    推荐一款国内首个开源全链路压测平台
    redis 你真的懂了吗?
    吊炸天的可视化安全框架,轻松搭建自己的认证授权平台!
    一条简单的更新语句,MySQL是如何加锁的?
    mysql 表删除一半数据,表空间会变小吗?
    调研字节码插桩技术,用于系统监控设计和实现
    这个开源工具把网页变成本地应用程序
    20160924-2——mysql常见问题集锦
    20160924-1——mysql存储引擎
    20160916-4:数据恢复
  • 原文地址:https://www.cnblogs.com/guangheli/p/12101286.html
Copyright © 2020-2023  润新知