それぞれの色は、DFSセグメントツリーノードとして、内部指図セグメントツリーを開き、右の値は出現、メンテナンス間隔、ツリー行の数を表します。
書式#include <iostreamの> 書式#include <stdio.hに> する#include < 文字列の.h> の#include <アルゴリズム> 書式#include <マップ> 使用して 名前空間はstd; const int型 MAXN = 2E5 + 6 。 構造体のエッジは{ int型、隣。 } E [MAXN * 2 ]。 構造体ノード{ int型のL、R。 int型のw; }ツリー[MAXN * 50 ]。 int型のヘッドは、[MAXN]、[MAXN] SIZ、トップ[MAXN]、息子[MAXN]。 INT D [MAXN]、FA [MAXN]、ID [MAXN]、RK [MAXN]、DFN [MAXN]、[MAXN] C。 INTのN、M、UU、VV、TOT、CNT。 int型RT [MAXN]。 マップ < int型、int型 > のp; ボイド追加(int型のx、int型のY){ E [ ++ CNT] .next = 頭部[X]。 E [CNT] .TO = Y。 ヘッド[X] = CNT。 } ボイド DFS1(INT U、INT F、int型の深さ){ D [U] = 深度。 FA [U] = F。 [U] SIZ = 1 。 以下のための(int型I =ヘッド[U]; I; I = E [I] .next){ int型、V = E [I] .TO。 もし(vは== f)を続けます。 DFS1(V、U、深さ + 1 )。 SIZ [U] + = SIZ [V]。 もし(SIZ [V]> SIZ [息子[U]) 息子[U] = V。 } } ボイド DFS2(int型 U、int型T){ トップ[U] =のT。 DFN [U] = ++ CNT。 もし(!息子[U]) のリターン; DFS2(息子[U]、T); 以下のための(int型 I =ヘッド[U]; I; I = E [I] .next) { int型、V = E [I] .TO。 もし(!!V =息子[U] && V = FA [U]) DFS2(vは、v)は、 } } ボイド変更(INT&X、int型の L、int型の Rは、int型 POSを、INT W) { もし X = ++ TOT(X!)。ツリー[X] .W + = W。 もし(L == R)のリターン; INT半ば=(L + R)>> 1 。 もし(POS <= MID)変更(ツリー[X] .L、L、中間、POS、W)。 それ以外の変更(木[X] .R、ミッド+1 、R、POS、W)。 } INTクエリ(int型のx、int型の L、int型の R、int型の L、INT R){ 場合(!(ツリー[X] .W)||(X))戻り 0 ; もし (L <= 1 && R <= R){ 戻りツリー[X] .W。 } INT半ば=(L + R)>> 1 。 int型 ANS = 0 ; もし(L <= MID)ANS + = クエリ(ツリー[X] .L、L、中、L、R)。 もし(R> MID)ANS + =クエリ(ツリー[X] .R、中間+ 1 、R、L、R)。 戻るANSを。 } INT qryRange(int型のx、int型の Y、int型K){ int型 RES = 0 。 一方(上部[X] =!トップ[Y]){ 場合(D [トップ[X] < D [トップ[Y])スワップ(X、Y) RES + =クエリ(RT [K]、1 、nは、DFN [トップ[X]、DFN [X])。 X = FA [TOP [X]]。 } もし、(D [Y]> D [X])スワップ(X、Y) RES + =クエリ(RT [K]、1 、nは、DFN [Y]、[X] DFN)。 リターンのres; } int型のmain(){ int型の和= 0 、Q。 同時に(〜のscanf(" %D%dの"、&N&Q)){ CNT = 0 。 合計 = 0 ; 以下のために(int型 i = 1 ; iが<= N; iが++ ){ scanf関数(" %のD "、&C [I])。 } のための(int型 i = 1 ; iが<= N iが++ ){ scanf関数(" %D%dの"、およびUU、&VV)。 追加(UU、VV); (VV、UU)を追加します。 } CNT = 0。 DFS1(1、0、1 )。 DFS2(1、1 )。 TOT = 0 ; 以下のために(int型 i = 1 ; iが<= N; iが++ ){ 場合(P [C [I]] == 0 ){ P [C [I] = ++ 和。 } 変更(RT [P [C [I]]]、 1、nは、DFN [i]は、1 )。 } チャー TMP [ 3 ]。 int型V、W、Uを。 しばらく(q--){ scanf関数(" %sの" 、TMP)。 もし(TMP [ 0 ] == ' C ' ) { scanf関数(" %d個の%のD "、&U、&W)。 変更(RT [P [C [U]]]、1、nは、DFN [U]、 - 1 )。 もし(!P [W])P [W] = ++ 合計。 変更(RT [P [] W]、1、nは、[U] DFN、1 )。 C [U] = W。 } 他{ scanf関数(" %D%D%D "、&U&V、& W) もし(!P [W])のprintf(" 0 \ N " ); 他のprintf(" %d個の\ n " 、qryRange(U、V、P)[W])。 } } } 戻り 0 。 }