P1600の愛は毎日実行しています

ポータル

$ U $のパス上のノードへのプレイヤーのパス$(x、y)は$の貢献を考えてみましょう

$のDEP [X] -dep [U]はW = $のLCA = LCA(x、y)は$、$ U $チェーン$ Xを、LCAの$、経路生成貢献$ 1 $もし設けられている場合にのみ[ U] $

前記$のDEP [i]は$ $ I $は$ wは、ノードの深さを示し、[I] $対象が$ Wの$与えられ、すなわち、式$のDEP [X] DEP [U]を= + W [U] $

場合チェーン$ U $ LCAの$、$ Yパスが生成される$ DEPの寄与場合に限り、[Y] -dep [U] = DIS(x、y)は、[U] $を-w

$ DIS(X、Y)の$ X、Yの$経路長、すなわち、式$のDEPを表す$ノード[Y] -dep [U] = DEP [X] + DEP [Y] -2dep [LCA] -w [U] $

$ -dep即[X] + 2dep [LCA] = DEP [U] [U] $を-w

ダイレクトリンクツリー分割し、各セグメントツリーの深さは、$ X $ $ $ Yに、パス$(x、y)は$セグメントは、ツリーの深さに直接対応するために、上記の二つのケースを別々に維持するために、動的開口点を維持しますすべてのノード$ 1 $ +

その深さは、これは両方の場合では、2つのセグメントの各々の深さは別々のツリーを維持すべきであることに注意し、[X] $と$ -depの深さ[X] + 2dep [LCA] $ $ DEPであります

後者の場合は、負の深さを持っている可能性があるため、深さはN $がプラスに変わる$となり、$ 2dep [LCA] -dep [X追加する必要があります ] + N $を、 そして$ LCAの$になりそうするように注意を払います減らすために1回、2回カウント

U $ $クエリノード場合DEP $へのクエリの深さ[U] + W [U] $と$ DEP [U] -w [U] + N $(ノート$ + N $)セグメントツリーノードU $ $以下のような値

ツリーラインのノードの最大数は、良好なノート、永久的な、音声及び高速書込み速度でマークされたコードセグメントツリー考慮すべき

#include <iostreamの> 
する#include <cstdioを> 
する#include <アルゴリズム> 
の#include <CStringの> 
する#include <cmath> 
の#include <地図>
 使用して 名前空間STD。
インラインint型リード()
{ 
    int型のx = 0、F = 1チャー CH = GETCHAR()。
    一方、(CH < ' 0 ' || CH> ' 9 '){ 場合(CH == ' - ')、F = - 1CH = GETCHAR()。
    (CH> = ' 0 ' && CH <= ' 9 '){X =(X << 1)+(X << 3)+(CH ^ 48)。CH = GETCHAR()。}
     戻りのx *のF。
} 
のconst  int型 N = 3E5 + 7 INTのN、M、W [N]。
INT、FIR [N] から [N << 1 ]、[N <<に1 ]、CNTT。
インラインボイドは(追加INT A、INT B){ から [A] [++ CNTT] =モミ。FIR [A] = CNTT。【CNTT] =用にB。}
 INT RT1 [N <<1 ]、[N <<のRT2 1 ]、T [N * 40 ]、L [N * 40 ]は、R [N * 40 ]、タグ[N * 40 ]、CNT;
 // セグメントツリー更新でRT1のU (X、LCA)は、セグメントツリーのメンテナンスU(LCA、Y)RT2 
空隙 INS(INT&O、int型の L、INT R&LT、INT QL、INT QR、INT K)を
{ 
    IF(!O)O = ++ CNT;
     IF(L> = QL && R&LT <= QR){タグ[O] + = K; 返す;}
     int型 MID = L + R&LT >> 1 ;
     IF(QL <= MID)INS(L [O] 、L、MID、QL、QR、K);
     IF(MID <QR)イン(R [O]、ミッド+ 1 、R、QL、QR、K)。
} 
INTクエリ(INT&O、int型の L、int型の R、int型のPOS)
{ 
    もし(O!)戻り 0 ;
    もし(L == R)戻りタグ[O]。
    INT半ば= L + R >> 1 リターン(?POS <=中間クエリ(L [O]、L、中間、POS):クエリ(R [O]、ミッド+ 1、R、POS))+ タグ[O]。
} 
int型の息子[N]・FA [N]、SZ [N]、DEP [N]、上位[N]、ID [N]、dfs_clock。
ボイド DFS1(INT X)
{ 
    SZ [X]= 1 ;
    以下のためにint型 [X] I =モミ; I; I = から[I])
    { 
        int型&V = [I]であり; もし(V == Faが[X])続けます
        FA [V] = xと; [X] + [V] = DEP DEP 1DFS1(V); SZ [X] + = SZ [V]。
        もし(SZ [V]> SZ [息子[X]])息子[X] = V。
    } 
} 
ボイド DFS2(int型のx、int型のTP)
{ 
    ID [X] = ++ dfs_clock。トップ[X] = TP。
    もし(息子[X])DFS2(息子[x]は、TP)。
    以下のためにint型 I = FIR [X]; I; I =[I])
    { 
        int型&V = [I]であり; もし(V == Faを[X] || V ==息子[X])続けます
        DFS2(V、V); 
    } 
} 
int型 LCA(int型のx、int型のY)
{ 
    ため(; TOP [X] = TOP [Y];!X = Faを[TOP [X]])
         であれば(DEP [TOP [X] < DEP [TOP [ Y])スワップ(X、Y)
    戻り DEPを[X] <DEP [Y]?X:Y。
} 
// DEP [X] -dep [U] == W [U] DEP [Y] -dep [U] == DEP [X] + DEP [Y] -2dep [LCA] -w [U]
 // [U] -dep W [U] + [X] == DEP DEP [X] + 2dep [LCA] == DEP [U] -w [U] 
ボイドワーク(int型のx、int型Y)
{ 
    int型 LCA = LCA(x、y)は、P。
    (; TOP [P] = TOP [LCA]!P = P = X Faを[TOP [P])
        イン(RT1 [DEP [X]、1、nは、ID [TOP [P]、ID [P]、1 )。
    イン(RT1 [DEP [X]、1、nは、ID [LCA]、ID [P]、1 )。
    (!P = Y; TOP [P] = TOP [LCA]; P = Faを[TOP [P])
        イン(RT2 [ 2 * DEP [LCA] -dep [X] + N]、1、nは、 ID [TOP [P]、ID [P]、1 )。
    イン(RT2 [ 2 * DEP [LCA] -dep [X] + N]、1、nは、ID [LCA]、ID [P]、1 )。
    イン(RT1 [DEP [X]、1、nは、ID [LCA]、ID [LCA]、 -1); // 注意LCA被算了两次
}
 INT (メイン)
{ 
    N =(読み取り)、M =読み取ります(); int型、B;
    以下のためにint型 I = 1 iは++; iがn <が
    { =(リード)、B = )(読み取ります。
        追加(A、B)。(B、A)を加えます。
    } 
    のためのint型 I = 1を W [I] = iが++; iが<= N) )(読み取ります。
    DEP [ 1 ] = 1DFS1(1)。DFS2(11 )。
    以下のためのint型私は=1 ; I <= M; iは++)A =リード()、B = 読み取る()、ワーク(B)
    以下のためにint型 i = 1 ; iが<= N; iは++ 
    { 
        int型 ANS1 =クエリ(RT1 [DEP [I] + W [I]、1 、nは、ID [I])。
        INT ANS2 =クエリ(RT2 [DEP [I] -w [I] + N]、1 、nは、ID [I])。
        printf(" %dの"、ANS1 + ANS2)。
    } 
    戻り 0 
}

 

おすすめ

転載: www.cnblogs.com/LLTYYC/p/11320602.html