コード:
#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を返します。 }