T3 DFSシミュレーションゲームシーケンスと+ + +フェンウィックツリーツリー右ポイントチェーン/右側のヒント

質問の意味:木を考えると、$ M $の操作があります。

操作0:$、$重量はS $ $(p、q)を添加パスに設定されている$ V $

操作1:$ V_を{生成し、右$ T $とセットで求め、パス$ I $および$ T $交差する場合、である(交差点を有し、$ S $路、点$ T $のセットが与えられますI} $の貢献)

データ範囲:路長$ \ leqslant 20 1 \ leqslant N $、$、M \ leqslant 10 ^ 5 $

パスの長さが0(すなわち、$ $ S全ての点)との言葉であればツリーと右のチェーンは、$ T $のポイントの私達のセットを見つけることです。

DFSは、オーダー+フェンウィックツリーを維持するために使用することができます。

任意の2点間のツリーが$ I $のポイントはその後、$ I-1 $エッジを通過します後場合という重要な特性は、エッジの数は常にポイントです-1。

そして、次のステップは、特に神です。

新しく追加されたパスの場合:重みプラス重みの反対側に追加経路上の点。

あなたはこのブロックからの通信経路を検索し、設定した場合には、ポイントと$ I $ $ I-1 $エッジを経過している必要があります。

1のみの寄与効果一旦達成さ - つまり、エッジ点の一定の数に等しいです。

右は、ルートと、我々はDFS順+ツリーの配列を使用する方法にポイントを維持するために。

#include <ベクトル>   
の#include <cstdioを> 
する#include <設定> 
の#include <CStringの> 
する#include <ストリング> 
の#include <アルゴリズム> 
の#define N 200007 
の#define長い長llの
名前空間stdを使用。   
ボイドsetIO(文字列s){ 
    = S +の文字列"に"。
    = S +アウト文字列"アウト。"; 
    freopenは(in.c_str()、 "R"、標準入力)。
    freopenは(out.c_str()、 "W"、STDOUT)。    
} 
構造体BIT {    
    LL C [N]。
    INT lowbit(INT T){ 
        戻りT&( - T)。
    } 
    ボイド更新(int型のx、int型V){ 
        一方(X <N){ 
            C [X] + =(LL)V。
            X + = lowbit(X)。
        }
    }
}
    LLクエリ(INT X){ 
        LL TMP = 0。
        一方、(X> 0){ 
            TMP + = C [X]。
            X- = lowbit(X)。
        } 
        TMP返します。
    } 
}木。   
int型TOT;    
整数N、M、L。   
int型のエッジ; 
int型DFN; 
int型のHD [N]。
[N << 1]〜INT。
INT NEX [N << 1]。
INTトップ[N]。
int型の息子[N];   
INTサイズ[N]。
INTのDEP [N]。
INT A [N]。  
INT FA [N]。     
int型ST [N];  
int型のED [N];   
INT Faを[N]。     
ベクター<INT> G [N]。         
ブールCMP(int型B、INTは){ 
    ST [] <ST [B]を返します。   
無効アドオン(int型のu、int型のV){ 
    NEX [++エッジ] = HD [U]。
    HD [U] =縁。
    [エッジ] = Vまで;  
} 
ボイドDFS1(INT U、INT FF){ 
    FA [U] = FF。
    サイズ[U] = 1。    
    DEP [U] = DEP [FF] +1。       
    {(; iはNEX [I] = [U] INT I = HD)用
        のint = Vに[I]を、
        (V == FF)場合{ 
            続けます。  
        } 
        DFS1(V、U)。
        サイズ[U] + =サイズ[V]。   
        IF(サイズ[V]>サイズ[息子[U]]){ 
            息子[U] = V。
        } 
    }    
} 
ボイドDFS2(INT U、INT TP){   
    トップ[U] = TP。    
    IF(息子[U]){ 
        DFS2(息子[U]、TP)。
    }
    {(; iはNEX [I]を= [U] INT I = HD)用 
        (![I] = FA [U] &&に[I] =息子[U]へ){場合
            DFS2([I]に、に[I])。
        } 
    } 
}   
int型LCA(int型のx、int型のY){ 
    一方(上面[X]!= TOP [Y]){ 
        DEP [トップ[X]]> DEP [トップ[Y]]?X = FA [トップ[X ] Y = FA [トップ[Y]。   
    } 
    戻りDEP [X] <DEP [Y] X:Y;?   
} 
//到根的权和         
LL和(INT X){ 
    戻りtree.query(ST [X])。        
}         
ボイドビルド(INT U){         
    ため(INT I = HD [U]; iは、iはNEX [I] =){ 
        int型V =に[I]を、  
        (V == FA [U])であれば{ 
            続けます。  
        }             
        ++ TOT。    
        FA [TOT = U。    
        FA [V] = TOT。        
        G [U] .push_back(TOT)。
        G [TOT] .push_back(V)。           
        (v)を構築します。      
    } 
}    
ボイドDFS(INT U){ 
    ST [U] = ++ DFN。  
    以下のために(; I <G [U] .size(); INT iが0 = ++ I){ 
        int型、V = G [U] [I]。
        //のprintf( "%D%D \ n"は、U、V)。  
        DFS(V); 
    } 
    ED [U] = DFN。  
} 
int型のmain(){ 
    setIO( "木")。
    私は、jはint型。         
    scanf関数( "%D%D%D"、&N、&M&L)。   
    ため(I 1 =、iは<N; ++ I){ 
        int型のX、Y。
        scanf関数( "%D%D"、およびX&Y)。
        (x、y)を加えます。
        (Y、X)を追加します。
    DFS1(1,0)。
    TOT = N。      
    ビルド(1); 
    DFS(1)。  
    (M--){一方
        INT OP。
        scanf関数( "%のD"、&OP)。  
        IF(OP == 0){                
            int型のP、Q、V、D = 1。
            scanf関数( "%D%D%D"、&P、およびQ&V)。   
            INT LCA = LCA(P、Q)。  
            一方、(P = LCA!){                  
                tree.update(ST [P]、D * V)。         
                tree.update(ED [P] + 1、-d * V)。   
                D * = - 1;   
                P = Faを[P]。  
            } 
            、D = 1。
            一方、(!Q = LCA){ 
                tree.update(ST [Q]、D * V)。 
                tree.update(ED [Q] + 1、D * V)。
                D * = - 1;   
                Q = Faを[Q]。          
            } 
            tree.update(ST [LCA]、V)。    
            tree.update(ED [LCA] + 1、-v)。
        }                          
        他{    
            int型、CNT = 0。
            scanf関数( "%のD"、&)。  
            {(; I <= A ++ iは= 1)のため
                のscanf( "%dの"、&A [++ CNT])。
            } 
            のscanf( "%d個"、&)。
            {(; I <= A ++ iは= 1)のため
                のscanf( "%dの"、&A [++ CNT])。
            }          
            ソート(A + 1、A + 1 + CNT、CMP)。   
            INT LCA = A [1]。  
            以下のために(I 2 =、iは<= CNT; ++ I){ 
                LCA = LCA(LCA、A [I])。
            LL ANS = 0。
            {(++ I; I <= CNT I = 1の)のための    
                ANS + =合計(A [I]) -合計(FA [LCA])。     
            } 
            (iは2 =; I <= CNT; ++ i)に対する{ 
                ans- =合計(LCA(A [i]が、A [I-1])) -合計(FA [LCA])。   
            }         
            のprintf( "%のLLD \ n"は、ANS)。  
        } 
    } 
    0を返します。
}

  

おすすめ

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