UOJ共有結合叔父のランダム化+ LCT保守情報サブツリー#207長沙旅行

注:$ LCT $ makerootはとき$リンク$でなければなりません。  

あなたは$ Y $ $ X $に接続する場合: 

$ Y $アクセスとスプレイその後、$ X $に直接接続された場合にのみ、あなたは$で$ Y $は明らかに適切ではない$ $(x、y)の間で息子に左のすべてを$スプレイことがわかりますA。 

コード: 

#include <cstdioを>   
する#include <ストリング> 
の#include <cstdlib> 
の#include <CTIME> 
の#include <アルゴリズム>        
の#define N 400006 

名前空間stdを使用。                                                    

名前空間IO { 
    ボイドsetIO(文字列s)
    { 
        = S +の文字列"に"。
        = S +アウト文字列"アウト。"; 
        freopenは(in.c_str()、 "R"、標準入力)。
        freopenは(out.c_str()、 "W"、STDOUT)。
    }                   
}。                

名前空間LCT { 

    に#define LSON T [X] .CH [0] 
    の#define rson T [X] .CH [1]    
    の#define GET(X)(T [T [X] .F] .CH [1] ==バツ)
    の#define ISR(X)(!(T [T [X] .F] .CH [0] == X || T [T [X] .F]。    

        int型の合計値、息子、CH [2]、REV、F。    
    } T [N]。      
    INT STA [N]。

    インラインボイド押し上げ(INT X)
    {     
        T [X] .SUM = T [LSON] .SUM ^ T [rson] .SUM ^ T [X] .son。        
    }     

    インラインボイドマーク(INT X)
    { 
        T [X] .rev ^ = 1; 
        スワップ(LSON、rson)。
    }   

    インラインボイドプッシュダウン(int型X)
    { 
        IF(T [X] .rev)
        { 
            T [X] .rev ^ = 1; 
            (LSON)マーク(LSON)であれば、
            (rson)マーク(rson)であれば、
        }  
    } 

    インラインボイド回転(int型X)
    { 
        [X] .F、折りINT古い= T = T [古い] .F、その= GET(X)。
        (!ISR)(旧)tは.CH [倍]場合は[トンを[倍] .CH [1] ==古い] = X;   
        。T [古い] .CH [] = T [X] .CH [^ 1]、T [T [古い] .CH [れる] F =古いです。
        T [X] .CH [れる^ 1] =古い、T [古い] .F = X、T [X] .F =折ります。
        腕立て伏せ(旧)、腕立て伏せ(x)は、
    } 

    インラインボイドスプレイ(INT X)
    { 
        int型のV = 0、U = X、FA。
        (!; ISR(U); STA [++ V = U U = T [U] .F)のためのSTA [++ V] = T [U] .F。   
        (; V; - v)のためのプッシュダウン(STA [V])。   
        (;(FA = T [X] .F)= U;!U = T [U] .F回し(X))のため
            であれば(!T [FA] .F = U)   
                を回転させ(GET(FA)==取得(x)は、FA:X);?   
    }   

    ボイドアクセス(INT X) 
        { 
    {
        用(int型、Y = 0; X; Y = X、X = T [X] .F)
            スプレイ(X)。              
            T [X] .son ^ = T [rson] .SUM。           
            T [X] .son ^ = T [Y] .SUM。            
            rson = Y。
            突き上げ(X)。
        } 
    } 

    ボイドMove_Root(INT X)
    {     
        アクセス(X)。      
        スプレイ(X)。
        マーク(X)。
    }      

    (int型x)を検索INT 
    { 
        アクセス(X)を、
        一方、(LSON)X = LSON。
        戻り値は、x; 
    } 

    ボイドLink_Edge(int型のx、int型のY)
    {      
        Move_Root(X)。
        Move_Root(Y)。    
        T [Y] .F = X。   
        T [X] .son ^ = T [Y] .SUM。     
        突き上げ(X)。   
    } 

    ボイドCut_Edge(int型のx、int型のY)
    {                
        Move_Root(X)。  
        アクセス(Y)、スプレイ(Y)。    
        T [T [Y] .CH [0]、F = 0。
        T [Y] .CH [0] = 0;      
        突き上げ(Y)。        
    }   

    ボイド更新(int型のx、int型V)
    { 
        アクセス(X)。                
        スプレイ(X)。   
        T [X] .son ^ = V。          
        突き上げ(X)。   
    }   

    int型の照会(int型のx、int型のY)
    { 
        Move_Root(X)。   
        アクセス(Y)。               
        戻りT [Y] .son。   
    }
 
    の#undef LSON 
    の#undef rson 

}。

構造体SS { 
    int型、X、W、Y、。   
    SS(INT X = 0、= 0のint Y = 0 W INT):X(X)、Y(Y)、(w)はwの{}   
} S [N]。  

int型のn;  

メイン()がINT 
{ 
    srand関数(20011011)を、
    // IO :: setIO( "入力");  
    INT I、J、M、TOT = 0、SU = 0。   
    scanf関数( "%D%D%D"、&I、&N、&M)。
    ため(I 1 =、iは<N; ++ I)
    { 
        int型のX、Y。
        scanf関数( "%D%D"、およびX&Y)。                
        LCT :: Link_Edge(X、Y)           
    }     
    のためには、(i 1 =; I <= M; ++ I)
    { 
        int型OP。
        scanf関数( "%のD"、&OP)。        
            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 =ランド()。   
            S [++ TOT = SS(X、Y、W)。         
            LCT ::更新(X、W)。    
            LCT ::更新(Y、W)。   
            SU ^ = W。
        } 
        IF(OP == 3)
        {     
            int型のX。
            scanf関数( "%のD"、&x)は、        
            LCT ::更新(S [X] .X、S [X] .W)。   
            LCT ::更新(S [X]・Y、S [X] .W)。    
            SU ^ = S [X] .W。    
        IF(OP == 4)
        {     
            int型のX、Y。
            scanf関数( "%D%D"、およびX&Y)。     
            printf( "%sの\ n"は、LCT ::クエリ(x、y)は== SU "YES": "NO")。       
        } 
    } 
    0を返します。
}

  

おすすめ

転載: www.cnblogs.com/guangheli/p/12101286.html