BZOJ 3786:ETTを探求する銀河

コード: 

#include <cstdioを> 
する#include <アルゴリズム> 
の#define N 200005 
の#defineっ長い長              
の#define LSONのT [X] .CH [0] 
の#define rson T [X] .CH [1]    
の#define setIO(S)freopenは(S ".IN"、 "R"、STDIN)
名前空間stdを使用。              
エッジをINT、ティム、ルート= 0、トップ。   
INT STA [N]、HDに[N]、[N]、NEX [N]、L [N]、R [N]、オイラー[N]、ヴァル[N]。          
インラインボイドaddedge(INT U、V INT)
{ 
    NEX [++エッジ] = HD [U]、HD [U] =縁、[エッジ]へ= V。   
}   
構造体スタック
{ 
    int型のx、I。         
    スタック(INT X = 0、I = 0 INT):X(x)は、I(I){}     
} A [N]。
構造体ノード   
{
    INTのSIZ、D、CH [2]、F。 
    IF(T [X] .lazy)
    { 
        IF(LSON)マーク(LSON、T [X] .lazy)。
    LLの合計値、ヴァル、怠惰。           
} T [N]。                     
インラインINT GET(INT X)
{ 
    [T [X] .F] .CH [1] == X Tを返します。   
} 
インラインボイド押し上げ(INT X)
{ 
    T [X] .siz = tの[LSON] .siz + T [rson] .siz + T [X] .D。   
    T [X] .SUM = T [LSON] .SUM + T [rson] .SUM + T [X] .val。
} 
インラインボイドマーク(INT X、LL V)
{ 
    T [X] .val + = 1LL * T [X] .D * V。                  
    T [X] .SUM + = 1LL * T [X] .siz * V。    
    T [X] .lazy + = V。         
} 
インラインボイドプッシュダウン(INT X)
{ 
        IF(rson)マーク(rson、T [X] .lazy)。
        T [X] .lazy = 0。      
    } 
} 
インラインボイド回転(INT X)
{ 
    int型古い= tの[X] .F、=さt(x)を取得= [古い] .Fを折ります。    
    T [古い] .CH [た] = tの[X] .CH [れる^ 1]、T [T [古い] .CH [れる] F =古いです。           
    T [X] .CH古い= [れる^ 1]、T = xと.F [古い]、T [X] .F =折ります。  
    IF(倍)T [倍]・CH = xで[T [1] ==古い[] .CH倍]。    
    腕立て伏せ(旧)、腕立て伏せ(x)は、
} 
インラインボイドスプレイ(INT X、INT&タール)
{ 
    int型、U = T [タール] .F、V = 0。
    (STA [++ V] = G、G = T [G] .F; G INT G = X)のために、          
    プッシュダウン(STA [i])と(; I> = 1 --I iが= V INT)のために、    
    (FAをint型;(FA = tの[X] .F)^ U(x)が回転する)ための
        (^ .F T [FA] U)の場合
            ((X)を取得==)(FAを取得FA回転:X? );    
    タール= X; 
}    
ボイドが解決()
{ 
    トップ= 0。         
            L [乃至[UI] = ++ティム。
            T [ティム] .D = 1、T [ティム] .val =(LL)のval [UI] [します]。                
        }
    【++トップ] =スタック(1、HD [1])、L [1] = ++ティム、T [ティム] .D = 1、T [ティム] .val =(LL)のval [1]。         
    (;トップ;)のために
    {      
        スタックU = A [トップ]。                  
        (UI)であれば
        {     
            [トップ] .I = NEX [A [トップ] .I]。      
            【++トップ] =スタック([UI]に、HD [] UI [します])。  
        {            
            R [UX] = ++ティム。    
            T [ティム] .D = -1、T [ティム] .val =(LL)-Val [UX]。          
            -  上;     
        }     
    } 
} 
int型のビルド(int型のL、R INT、INT FF)
{ 
    int型ミッド=(L + R)>> 1。           
    T [中間] .F = FF。      
    (MID> L)Tであれば、[中間] .CH [0] =ビルド(L、ミッド- 1、MID)。   
    IF(R> MID)T [中間] .CH [1] =構築(MID + 1、R、MID)。        
    (MID == 1)T [中間] .CH [0] =ティム+ 1、T [ティム+ 1] .F =ミッド場合;       
    (MID == TIM)T [中間]は[1] =ティム+ 2、T [ティム+ 2] .F =半ばを.CH場合。     
    腕立て伏せ(中旬)。              
    半ばを返します。       
}  
INTプレ(INT X)
{        
    int型G =ルート;  
    スプレイ(X、根)。   
    (; rson、プッシュダウン(X)、X = X = rson LSON)のために、
    スプレイ(G、根)。    
    Xを返します。    
} 
INT NXT(INT X)
{ 
    int型G =ルート。
    スプレイ(X、根)。     
    (; LSON、プッシュダウン(X)、X = X = LSON rson)のために、    
    スプレイ(G、根)。
    Xを返します。         
} 
int型のmain()
{ 
    // setIO( "入力")。  
    INTのN、M、I、J、X、Y。
    scanf関数( "%のD"、&N); 
    以下のための(I = 2; iが<= N; ++ I)のscanf( "%d個"、&x)は、addedge(X、I)。        
    用(i = 1; iは= N <; ++ I)のscanf( "%dを" &ヴァル[I])。   
    ()、ルート=ビルド(1、ティム、0)を解きます。                              
    scanf関数( "%のD"、&M)。
    用(int型CAS = 1; CAS <= M; ++ CAS)
    { 
        文字列str [4]。  
        scanf関数( "%sの"、STR)。    
        (STR [0] == 'Q')なら
        、{ 
            T -のscanf( "%dの"、およびX)、スプレイ(L [x]は、根)のprintf( "%LLDする\ n"、T [ルート] .SUM [T [ルート] .CH [1]の合計)。          
        } 
        (STR [0] == 'C')であれば
        {         
            scanf関数( "%D%dの"、およびX&Y)。        
            INT 1 =プレ(L [X])、R = NXT(R [X])、キー、K。       
            スプレイ(L、根)、スプレイ(R、T [ルート] .CH [1])、キー= tの[T [ルート] 1] [.CH]をch [0]。
            Tは、[キー] .F = T [T [ルート] [1]・CH]をch [0] = 0、押し上げ(T [ルート] [1]・CH)、押し上げ(ルート)。     
            スプレイ(L [Y]、根)、スプレイ(NXT(L [Y])、T [ルート] .CH [1])。      
            T [T [ルート] .CH [1]。をch [0] =キー、T [キー] .F = T [ルート] .CH [1]、押し上げ(T [ルート] .CH [1])、突き上げ(ルート)。     
        }     
        (STR [0] == 'F')であれば
        { 
            scanf関数( "%D%dの"、およびX&Y)。             
            スプレイ(プレ(L [X])、根)、スプレイ(NXT(R [X])、T [ルート] .CH [1])。      
            。INTキー= tの[T [ルート] .CH [1]をCH [0]。    
            マーク(キー、1LLの*のY)。         
        }             
    }                 
    0を返します。    
}

  

再帰: 

#include <cstdioを> 
する#include <アルゴリズム> 
の#define N 200005 
の#defineっ長い長              
の#define LSONのT [X] .CH [0] 
の#define rson T [X] .CH [1]    
の#define setIO(S)freopenは(S ".IN"、 "R"、STDIN)
名前空間stdを使用。              
INTエッジ、ティム、ルート= 0。   
INT STA [N]、HDに[N]、[N]、NEX [N]、L [N]、R [N]、オイラー[N]、ヴァル[N]。        
インラインボイドaddedge(INT U、V INT)
{ 
    NEX [++エッジ] = HD [U]、HD [U] =縁、[エッジ]へ= V。   
}   
構造体ノード   
{ 
    int型SIZ、D、CH [2]、F。
    LLの合計値、ヴァル、怠惰。           
} T [N]。                     
インラインINT GET(int型X)
{
    Tを返す[T [X] .F] .CH [1] == X。   
} 
インラインボイド押し上げ(INT X)
{ 
    T [X] .siz = tの[LSON] .siz + T [rson] .siz + T [X] .D。   
    T [X] .SUM = T [LSON] .SUM + T [rson] .SUM + T [X] .val。
} 
インラインボイドマーク(INT X、LL V)
{ 
    T [X] .val + = 1LL * T [X] .D * V。                  
    T [X] .SUM + = 1LL * T [X] .siz * V。    
    T [X] .lazy + = V。         
} 
インラインボイドプッシュダウン(INT X)
{ 
    IF(T [X] .lazy)
    { 
        IF(LSON)マーク(LSON、T [X] .lazy)。
        IF(rson)マーク(rson、T [X] .lazy)。
        T [X] .lazy = 0。      
    } 
} 
インラインボイド回転(INT X)
{ 
    =さt(x)を取得= [古い] .Fを折る、[X] .F古い= tをint型。    
    T [古い] .CH [た] = tの[X] .CH [れる^ 1]、T [T [古い] .CH [れる] F =古いです。           
    T [X] .CH古い= [れる^ 1]、T = xと.F [古い]、T [X] .F =折ります。  
    IF(倍)T [倍]・CH = xで[T [1] ==古い[] .CH倍]。    
    腕立て伏せ(旧)、腕立て伏せ(x)は、
} 
インラインボイドスプレイ(INT X、INT&タール)
{ 
    int型、U = T [タール] .F、V = 0。
    (STA [++ V] = G、G = T [G] .F; G INT G = X)のために、          
    プッシュダウン(STA [i])と(; I> = 1 --I iが= V INT)のために、    
    (FAをint型;(FA = tの[X] .F)^ U(x)が回転する)ための
        (^ .F T [FA] U)の場合
            ((X)を取得==)(FAを取得FA回転:X? );    
    タール= X; 
} 
ボイドDFS(UをINT)
{ 
    L [U] = ++ティム。       
    T [ティム] .D = 1、T [ティム] .val =(LL)のval [U]。      
    以下のために(INT I = HD [U]; I; I = NEX [i])とDFS(の[I])。    
    R [U] = ++ティム。     
    T [ティム] .D = -1、T [ティム] .val =(LL)-Val [U]。          
} 
INTビルド(int型のL、R INT、INT FF)
{ 
    int型ミッド=(L + R)>> 1。           
    T [中間] .F = FF。      
    (MID> L)Tであれば、[中間] .CH [0] =ビルド(L、ミッド- 1、MID)。   
    IF(R> MID)T [中間] .CH [1] =構築(MID + 1、R、MID)。        
    (MID == 1)T [中間] .CH [0] =ティム+ 1、T [ティム+ 1] .F =ミッド場合;       
    (MID == TIM)T [中間]は[1] =ティム+ 2、T [ティム+ 2] .F =半ばを.CH場合。     
    腕立て伏せ(中旬)。   
    //のprintf( "%D%D%D \ n"は、半ば、T [中間] .CH [0]、T [中間]は.CH [1])。            
    半ばを返します。       
}   
int型のプレ(INT X)
{        
    int型G =ルート。  
    スプレイ(X、根)。   
    (; rson、プッシュダウン(X)、X = X = rson LSON)のために、
    スプレイ(G、根)。    
    Xを返します。    
} 
INT NXT(INT X)
{ 
    int型G =ルート。
    スプレイ(X、根)。     
    (; LSON、プッシュダウン(X)、X = X = LSON rson)のために、    
    スプレイ(G、根)。
    Xを返します。         
} 
int型のmain()
{ 
    // setIO( "入力")。  
    INTのN、M、I、J、X、Y。
    scanf関数( "%のD"、&N); 
    ための式(I = 2; iが<= N; ++ I)のscanf( "%d個"、&x)は、addedge(X、I)。        
    用(i = 1; iは= N <; ++ I)のscanf( "%dを" &ヴァル[I])。   
    DFS(1)、ルート=ビルド(1、ティム、0);                              
    scanf関数( "%のD"、&M)。
    用(int型CAS = 1; CAS <= M; ++ CAS)
    { 
        文字列str [4]。  
        scanf関数( "%sの"、STR)。    
        IF(STR [0] == 'Q')
        { 
            T -のscanf( "%dの"、およびX)、スプレイ(L [x]は、根)のprintf( "%LLDする\ n"、T [ルート] .SUM [T [ルート] .CH [1]の合計)。          
        } 
        (STR [0] == 'C')であれば
        {         
            scanf関数( "%D%dの"、およびX&Y)。        
            スプレイ(L、根)、スプレイ(R、T [ルート] .CH [1])、キー= tの[T [ルート] 1] [.CH]をch [0]。
            Tは、[キー] .F = T [T [ルート] [1]・CH]をch [0] = 0、押し上げ(T [ルート] [1]・CH)、押し上げ(ルート)。     
            スプレイ(L [Y]、根)、スプレイ(NXT(L [Y])、T [ルート] .CH [1])。      
            T [T [ルート] .CH [1]。をch [0] =キー、T [キー] .F = T [ルート] .CH [1]、押し上げ(T [ルート] .CH [1])、突き上げ(ルート)。     
        }     
        場合(STR [0] == 'F')
        { 
            scanf関数( "%D%dの"、およびX&Y)。             
            スプレイ(プレ(L [X])、根)、スプレイ(NXT(R [X])、T [ルート]。      
            。INTキー= tの[T [ルート] .CH [1]をCH [0]。    
            マーク(キー、1LLの*のY)。         
        }             
    }                  
    0を返します。    
}

  

おすすめ

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