Hのnewcoder 79F小さな変更ツリーのルートとルートパーティションDP +

コード: 

#include <cstdioを> 
する#include <アルゴリズム>   
の#include <ベクトル>     
の#include <cmath>    
の#include <地図> 
の#define N 100003 
の#defineっ長い長          
の#define setIO(S)freopenは(S ".IN"、「R "STDIN)、freopenは(S" .out」を、 "W"、STDOUT)   
使用して名前空間std。
名前空間IO 
{ 
    チャー*のP1、P2 *、BUF [100000]。
    #define NC()(P1、P2 == &&(P2 =(P1 = BUF)+関数fread(BUF、1,100000、STDIN)、P1 == P2)EOF:* P1 ++)
    int型のreadInt(){int型のx = 0 ; チャーC = NC()。一方、(C <48)C = NC()。一方、(C> 47)x =(((X << 2)+ X)<< 1)+(C ^ 48)、C = NC()。Xを返す;} 
    readll 11(){LL X = 0。チャーC = NC()。一方、(C <48)C = NC()。一方、(C> 47)x =(((X << 2)+ X)< <1)+(C ^ 48)、C = NC()。
戻りX;} }。
戻りX;} ベクトル<整数> G [N]、TY [N]、ノード。      
整数nを、エッジ、ティム、toop。      
LL DIS [N]、深さ[N]。    
int型COL [N]、税金[N]、ID [N]、A [N]、サイズ[N]、S [N]。
int型のHD [N]、NEX [N << 1]、[N << 1]、トップ[N]、DFN [N]、FA [N]、DEP [N]、息子[N]、SIZ [Nに]; 
LLヴァル[N << 1]。     
BOOL CMP(INT A、INT B)
{ 
    戻りDFN [A] <DFN [B]。    
}     
インラインボイドaddedge(INT U、INT V、INT C)
{ 
    NEX [++エッジ] = HD [U]、HD [U] =縁、[エッジ]にV、ヴァル[縁] = 1LLの* cを=。
} 
ボイドDFS1(INT U、int型FF)
{ 
    int型I、V。
    FA [U] = FFの、DEP [U] = DEP、1 + [FF] [U] = ++ティムDFN、SIZ [U] = 1。
    (; I; I = HD [U] I = NEX [i])とするため 
    {
        V = [I]であり; 
        (vは== FF)続けるならば、
        深さ[V] =深さ[U] + 1LL *ヴァル[I]、DFS1(V、U)、SIZ [U] + = SIZ [V]。
        IF(SIZ [V]> SIZ [息子[U])息子[U] = V。    
    } 
} 
ボイドDFS2(INT U、INT TP)
{      
    トップ[U]はTPを=。   
    IF(息子[U])DFS2(息子[U]、TP)。    
    以下のために(INT I = HD [U]; I; I = NEX [I])
    { 
        int型V =乃至[I]。
        もし(V == FA [U] || V ==息子[U])続けます。
        DFS2(V、V);     
    }   
} 
インラインINT LCA(int型のx、int型Y)
{ 
    一方(上面[X] ^トップ[Y])
    { 
        DEP [トップ[X]]> DEP [Y]トップ[]?X = FA [TOP [X]:Y = FA [トップ[Y]。
    }
    DEPを返す[X] <DEP [Y]?X:Y。     
}     
インラインLLディス(int型のx、int型Y)
{ 
    戻り深さ[X] +深さ[Y] - (深さ[LCA(X、Y)] << 1)。   
} 
ボイドsolve1(INT U、INT FF、INT CUR)
{ 
    サイズ[U] =(COL [U] == CUR)、DIS [U] = 0;                 
    以下のために(INT I = HD [U]; I; I = NEX [I])
    { 
        int型V =乃至[I]。
        (vは== FF)続けるならば、  
        solve1(V、U、CUR)、サイズ[U] + =サイズ[V]、DIS [U] + =(DIS [V] + 1LL *サイズ[V] *ヴァル[I])。   
    }             
}   
ボイド(INT U、INT FF、INT CUR)を解く
{   
    (I = NEX [I];私は= HD [U] INT)のために
    { 
        [I]へのint型、V =。
        (vは== FF)続けるならば、     
        IF(!S [toop] = LCA)addvir(LCA、S [toop])、S [toop] = LCA。    
        DIS [V] + =(DIS [U] - DIS [V] - 1LL・サイズ[V] *ヴァル[I] + 1LL *(税[CUR] -サイズ[V])*ヴァル[I])。    
        (V、U、CUR)を解きます。                 
    }    
} 
インラインボイドaddvir(INT U、V INT)
{ 
    G [U] .push_back(V)。    
} 
インラインボイドインサート(INT X)
{ 
    (toop <2)であれば
    { 
        S [++ toop] = xと; 
        返します。
    } 
    int型LCA = LCA(X、S [toop])。  
    IF(!LCA = S [toop])
    { 
        一方(toop> 1つの&& DEP [S [toop - 1]]> = DEP [LCA])addvir(S [toop - 1]、S [toop])、 - toop;  
    } 
    [++ toop] = xをS。      
}   
ボイドプレ(INT U、INT FF、INT CUR)
{ 
    サイズ[U] =(COL [U] == CUR)、DIS [U] = 0;     
    ための式(I = 0 int型、iはGを<U] .size(); ++ I)
    { 
        int型、V = G [U] [I]。  
        プレ(V、U、CUR)、サイズ[U] + =サイズ[V]、DIS [U] + = DIS [V] + 1LL *サイズ[V] *ディス(V、U)。   
    }     
} 
ボイドワーク(INT U、INT FF、INT CUR)
{ 
    ための式(I = 0 int型、iはGを<U] .size(); ++ I)
    { 
        int型、V = G [U] [I]。       
        DIS [V] + =(DIS [U] - DIS [V] - 1LL・サイズ[V] *ディス(U、V)+ 1LL *(税[CUR] -サイズ[V])*ディス(U、V )); 
        仕事(V、U、CUR)。     
    } 
} 
ボイドクリア(INT U)
{ 
    サイズ[U] = DIS [U] = 0;
    (I = 0 int型、iがG [U]は.sizeを()<; ++ i)についてクリア(G [U] [I])。 
        int型A =のreadInt()、B =のreadInt()、C =のreadInt()。
    G [U] .clear();   
} 
構造体ノード
{ 
    A、B INT。
} [N]を尋ねます。  
ベクター<整数> P [N]。      
ベクター<LL>答え[N]。       
INTポイント[N]。  
メインINT()
{ 
    名前空間IOを使用して、
    // setIO( "入力"); 
    int型I、J、IDX = 0、M、Q; 
    N =のreadInt()。
    M = SQRT(N)。
    。COL [I] =のreadInt()、++税[COL [I]、TY [COL [I]一back(I)、(I ++; iが<= N I = 1)のために                                  
    用(i = 1; iがn <; ++ i)が
    { 
        addedge(A、B、C)、addedge(B、C)。
    }       
    DFS1(1、0)、DFS2(1、1)。  
    用(i = 1; iが<= N; ++ I)IF(税[I]> = m)のID [I] = ++ IDX。          
    Q =のreadInt()。
    (; I <= Q; I = 1 ++ i)について
    { 
        尋ねる[I] .A =のreadInt()、[I] .B =のreadInt()を尋ねます。
        スワップ(税<税[尋ねる[I] .B] [[I] .A尋ねる])の場合([i]が.A、尋ねる尋ねる[I] .B)。  
        .push_back [I] .A [尋ねる] P(税込> = M [i]は.A [尋ねる])(.B [i]を尋ねる)場合。    
    }         
    (i = 1;私は、<= N I ++)
    { 
        (M =税[I])場合>は、
        { 
            solve1(1、0、i)を、(iは1、0)を解きます。       
            用(J = 0であり、j <P [i]の.size(); ++ J)
            {
                用(int型のk = 0; K <TY [CUR] .size(); ++、K) 
                int型CUR = P [I] [J]。     
                LL再= 0。         
                { 
                    再+ = DIS [TY [CUR] [K]。   
                } 
                [I] .push_back(再)答えます。      
            } 
        } 
    }            
    のための(INT CAS = 1; CAS <= Q; ++ CAS)
    { 
        B、INT。
        = [CAS] .A、B = [CAS] .B尋ねる尋ねます。       
        ?IF(税[A]> = M)のprintf( "%LLDする\ n"、== Bの回答[A] [ポイント[A] ++ / 2:答え[A] [ポイント[A] ++ ]);               
        他の
        {       
            int型TMP = 0;          
            LL再= 0。
            (i = 0; I <TY [A] .size(); ++ i)に対するA [++ TMP] = TY [A] [I]。
            [I] A [++ TMP] = TY [B](++ I; I <TY [B] .size()I = 0)ため、   
            ソート(A + 1、A + 1 + TMP、CMP)。   
            TMP =ユニーク(A + 1、A + 1 + TMP) - (A + 1)。         
            toop = 0; 
            ;(![1] = 1)++ toop] = 1秒であれば           
            用(i = 1; I <= TMP; ++ i)から(A [i])とインサート。
            (toop> 1)addvir(S [toop - 1]、S [toop])一方、--toop。        
            プレ(1、0、b)は、ワーク(1、0、B)。  
            再+ = DIS [TY [A] [I]];(; I <TY [A] .size()++ I I = 0)のための  
            printf( "%LLDする\ n"、== BのRE / 2:再?)。  
        } 
    } 
    0を返します。   
}

  

おすすめ

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