コード:
#include <cstdioを> する#include <ベクトル> の#include <アルゴリズム> の#define N 300000 の#defineっ長い長 の#define setIO(S)freopenは(S ".IN"、 "R"、STDIN)、freopenは(S」。アウト」、 "W"、STDOUT) 名前空間stdを使用。 エッジをINT、N。 int型のHDに[N]、[N << 1]、NEX [N << 1]、ヴァル[N << 1]。 ボイド追加(INT U、V INT、INT C) { NEX [++エッジ] = HD [U]、HD [U] =エッジは、[エッジ]にVが=ヴァル[エッジ]はCを=。 } 名前空間ツリー { int型のサイズ[N]、息子[N]、トップ[N]、FA [N]、DEP [N]、DIS [N]。 ボイドDFS1(INT U、int型FF) { FA [U] = FFの、サイズ[U] = 1。 ([i]はI = NEX; I I = HD [U]をint型)のための (![I] = FF)があれば 、{ = DIS [U] +ヴァル[I] [I]に] [U] + 1、DIS = DEP [I]に] DEP。 ([I]、Uへ)DFS1。 サイズ[U] + =サイズ[I] [します]。 IF(サイズ[する[I]]>サイズ[息子[U])息子[U] [I]を=。 } } ボイドDFS2(INT U、INT TP) { トップ[U]はTPを=。 IF(息子[U])DFS2(息子[U]、TP)。 以下のために(int型私= HD [U]; I; I = NEX [i])と あれば(へ[I] =息子[U] &&へ[i]を= FA [U]!!)[i]は、へへDFS2( [私]); } int型LCA(int型のx、int型のY) { 一方(上面[X] = TOP [Y]!) DEP [TOP [X]]> DEP [トップ[Y] X = FA [TOP [X]]?: Y = FA [トップ[Y]。 DEPを返す[X] <DEP [Y]は、x:yの。 } int型ディス(int型のx、int型Y) { DISを返す[X] + DIS [Y] - (DIS [LCA(X、Y)] << 1)。 } }。 { int型の根、SN; VIS int型の年齢[N]、サイズ[N]、MX [N]、[N]、Faを[N]; 構造体ノード { int型V、D。 TOT LL; ノード(INTのV = 0、INT D = 0、LL TOT = 0):V(V)、D(D)、TOT(TOT){} }。 ベクター<ノード> G [N]、F [N]。 ブールCMP(ノードA、ノードB) { 戻りAV <BV。 } ボイドgetroot(INT U、int型FF) { サイズ[U] = 1、MX [U] = 0; 以下のための(int型I = HD [U]; I; I = NEX [i])と するif(!!の[i]を= FF && VIS [に[I]]) getroot、サイズ[U([i]は、Uへ) ] + =サイズ[する[I]、MX [U] = MAX(MX [U]、[Iの大きさ[]])。 MX [U] = MAX(MX [U]、SN-サイズ[U])。 IF(MX [U] <MX [ルート])ルート= U。 } ボイドDFS(INT U、INT FF、INT RT、INT DEP) G [RT] .push_back(ノード(年齢[U]、DEP、0)); もし(FA [RT])F [RT] .push_back(ノード(年齢[U]、木::ディス(FA [RT]、U)、0)); 以下のために(INT I = HD [U]; I; I = NEX [I]) { int型V =乃至[I]。 (V == FF || VIS [V])続けるならば、 DFS(V、U、RT、DEP +ヴァル[I])。 } } ボイドが解決する(INT U) { VIS [U] = 1。 G [U] .push_back(ノード(-100,0,0))。 F [U] .push_back(ノード(-100,0,0))。 G [U] .push_back(ノード(1000000004,0,0))。 F [U] .push_back(ノード(1000000004,0,0))。 DFS(U 0、U、0); ソート(G [U] .begin()、G [U] .END()、CMP)。 ソート(F [U] .begin()、F [U] .END()、CMP)。 F [U] [i]は.tot = F [U] [I-1] .tot + 1LL * F [U](++ I; Iは、F [U] .size()<I 1 = INT)のために[I] .D。 以下のために(INT i = 1; iはGを<U] .size(); ++ I)G [U] [i]は.tot = G [U] [I-1] .tot + 1LL * G [U] [I] .D。 (; I I = NEX [i]の値int i = HD [U])のための (!VIS [する[I])であれば { SN =サイズ、根= 0、getroot(の[I [I]乃至] ]、U)・FA [ルート] = Uは、(ルート)を解きます。 } } (int型のL、R INT、INT U)動作っ { LL再= 0。 int型のL、R、中間、ANS1 = 0、ANS2 = 0。 L = 0、R = G [U] .size() - 1; 一方、(L <= R) { 半ば=(L + R)>> 1。 IF(G [U] [中間] .V> = L)ANS1 =中間、R =ミッド1。 他リットル=ミッド+ 1; } 、L = 0、R = G [U] .size() - 1; 一方、(L <= R) { 半ば=(L + R)>> 1。 IF(G [U] [中間] .V <= R)ANS2 =中間、L =ミッド+ 1。 他に、R =半ば1; } IF(ANS1> 0 && ANS2 <G [U] .size() - 1 && ANS1 <= ANS2) 再+ = G [U] [ANS2] .tot-G [U] [ans1-1] .tot。 int型U = U; 用(; Faを[U]; U = Faを[U]) { int型anss1 = ANS1、anss2 = ANS2。 L = 0、R = G [Faを[U]サイズ() - 1、ANS1 = 0。 一方、(L <= R) { 半ば=(L + R)>> 1。 IF(G [Faを[U] [中間] .V> = L)ANS1 =中間、R =ミッド1。 他リットル=ミッド+ 1; } 、L = 0、R = G [Faを[U]サイズ() - 1、ANS2 = 0。 一方、(L <= R) { 半ば=(L + R)>> 1。 IF(G [Faを[U] [中間] .V <= R)ANS2 =中間、L =ミッド+ 1。 他に、R =半ば1; } IF(ANS1> ANS2)続けます。 TMP + = G [Faを[U] [ANS2] .tot-G [Faを[U] [ans1-1] .tot。 IF(anss2> = anss1)tmp- = F [U] [anss2] .tot-F [U] [anss1-1] .tot。 IF(anss1 <= anss2) TMP = TMP +(LL)(ANS2-ans1-(anss2-anss1 + 1)+1)* 1LL *ツリー::ディス(U・FA [U])。 他 TMP = TMP +(LL)(ANS2、ANS1 + 1)* 1LL *ツリー::ディス(U・FA [U])。 + = tmpの再; } 戻り再。 } int型のmain() { // setIO( "入力")。 int型Q、A、I、J。 scanf関数( "%D%D%D"、&N、&Q&A)。 scanf関数( "%dの"、および年齢[I])は、(i ++; iが<= N I = 1)のために、 (++ I; iがn <I = 1)のために { A、B、C INT。 scanf関数( "%D%D%D"、&、& (A、Bは、C)、追加(B、C)。 ツリー:: DFS2(1,1); MX [0] = SN = N、getroot(1,0)、(ルート)を解きます。 LL lastans = 0。 用(int型CAS = 1; CAS <= Q; ++ CAS) { int型、U、A、B、L、R。 scanf関数( "%D%D%D"、U、及び、・B&)。 L =(A + lastans)%A、R =(B + lastans)%のA。 IF(L> R)スワップ(L、R)。 printf( "%LLDする\ n"、lastans =仕事(L、R、U))。 } 0を返します。 }