トピックリンク:
https://www.luogu.com.cn/problem/P3833
アイデア:
ツリーボードセクションのタイトル
コード:
#include <ビット/ STDC ++ H> に#define LSノード<< 1、L、中間 の#define RSノード<< 1 | 1、中間+ 1、R 使用して 名前空間STDを、 const int型 MAXN = 1E5 + 5 。 typedefの長い 長いLL。 LLのn; int型のヘッド[MAXN]、TOT; 構造体ノード { int型NXT、であり; } E [MAXN << 1 ]。 ボイド追加(int型のx、int型のY) { E [TOT] .TO = Y、E [TOT] .nxt =頭部[X]、ヘッド[X] = TOT ++ 。 } 無効 add_edge(int型X、int型のY) { (x、y)を追加し、追加(Y、X)。 } int型のDEP [MAXN]、F [MAXN]、SZ [MAXN]、息子[MAXN]。 ボイド DFS(INT U、INT FA) { DEP [U] = DEP [FA] + 1 ; F [U] = FA; SZ [U] = 1 。 以下のために(INTは iはヘッド= [U]は;〜私は= E [I] .nxt) { int型、V = E [I] .TOと、 もし(!V = FA) { DFS(V、U); SZ [U] + = SZ [V]。 もし(SZ [V]> SZ [息子[U]]) 息子[U] = V; } } } int型のID [MAXN]、トップ[MAXN]、CNT。 ボイド DFS2(INT U、INT T) { トップ[U] = T; ID [U] = ++ CNT。 もし(息子[U]) DFS2(息子[U]、T); 以下のために(INTは iはヘッド= [U]は;〜私は= E [I] .nxt) { int型、V = E [I] .TOと、 もし(!!V = F [U] && V = 息子[U]) DFS2(V、V); } } LLツリー[MAXN << 2 ]、怠惰[MAXN << 2 ]。 ボイド push_up(int型ノード) { ツリー[ノード] =ツリー[ノード<< 1 ] +ツリー[ノード<< 1 | 1 ]。 } ボイドビルド(int型ノード、INT L、INT R) { 場合(L == R)のリターン; INTの半ば=(L + R)>> 1 。 ビルド(LS);ビルド(RS); push_up(ノード)。 } ボイド push_down(int型ノード、INT L、INT R、INT MID) { 場合(怠惰[ノード]) { ツリー[ノード << 1 ] + =(MID-L + 1)* 怠惰[ノード]。 ツリー[ノード << 1 | 1 ] + =(R-MID)* 怠惰[ノード]。 怠惰[ノード << 1 ] + = 怠惰[ノード]。 怠惰な[ノード << 1 | 1 ] + = 怠惰[ノード]。 怠惰[ノード] = 0 ; } } ボイド更新(int型ノード、INT L、INT R、int型のx、int型のy、int型k)を { 場合ツリー[ノード]。(L> = X && R <= Y) { ツリー[ノード] + =(R-L + 1)* K;怠惰[ノード] + = K。リターン; } int型のミッド=(L + R)>> 1 。 push_down(ノード、L、R、MID)。 もし(x <= MID) 更新(LS、X、Y、K)。 もし(Y> MID) 更新(RS、X、Y、K)。 push_up(ノード)。 } LLクエリ(INTノード、INT L、INT R、int型のx、int型Y) { 場合(L> = X && R <= y)を返し LL ANS = 0 。 INTの半ば=(L + R)>> 1 。 push_down(ノード、L、R、MID)。 もし(x <= MID) ANS + = クエリ(LS、X、Y) もし(Y> MID) ANS + = クエリ(RS、X、Y) 戻り値は、ANS; } ボイド tree_update(int型のx、int型のy、int型Z) { int型の FX = TOP [X]、FY = TOP [Y]。 一方、(!FX = FY) { 場合(DEP [FX] < DEP [FY])スワップ(x、y)は、スワップ(FX、FY)。 更新(1、1 、CNT、ID [FX]、ID [x]は、Z)。 X = F [FX]、FX = TOP [X]。 } もし(ID [X]> ID [Y])スワップ(X、Y) アップデート(1、1 、CNT、ID [x]は、ID [Y]、Z); } int型のmain() { scanf関数(" %のLLD "、&N) memsetの(頭、 - 1、はsizeof (ヘッド))。 以下のために(INT iが= 1 ; N I <; I ++ ) { LL X、Y; scanf関数(" %LLD%LLD "、およびX& 0 Y)。 add_edge(X、Y) } DFS( 、0); DFS2(0、0 ); ビルド(1、1 、N) INT Q; scanf関数(" %のD "、&Q)。 一方、(q-- ) { チャー STR [ 2 ]。 scanf関数(" %S " 、STR)。 もし(STR [ 0 ] == ' A ' ) { LL X、Y、Z; scanf関数(" %LLD%LLD%LLD "、およびX&Y、およびZ); tree_update(X、Y、Z)。 } 他 { LL X; scanf関数(" %のLLD "、およびX);のprintf(" %のLLD \ n "、クエリ(1、1、nは、ID [x]は、ID [X] + SZ [X] - 1 )) ; } } 戻り 0 。 }