コード:
#include <cstdioを> する#include <アルゴリズム> の#define N 200005 の#defineっ長い長 の#define LSONのT [X] .CH [0] の#define rson T [X] .CH [1] の#define setIO(S)freopenは(S ".IN"、 "R"、STDIN) 名前空間stdを使用。 エッジをINT、ティム、ルート= 0、トップ。 INT STA [N]、HDに[N]、[N]、NEX [N]、L [N]、R [N]、オイラー[N]、ヴァル[N]。 インラインボイドaddedge(INT U、V INT) { NEX [++エッジ] = HD [U]、HD [U] =縁、[エッジ]へ= V。 } 構造体スタック { int型のx、I。 スタック(INT X = 0、I = 0 INT):X(x)は、I(I){} } A [N]。 構造体ノード { INTのSIZ、D、CH [2]、F。 IF(T [X] .lazy) { IF(LSON)マーク(LSON、T [X] .lazy)。 LLの合計値、ヴァル、怠惰。 } T [N]。 インラインINT GET(INT X) { [T [X] .F] .CH [1] == X Tを返します。 } インラインボイド押し上げ(INT X) { T [X] .siz = tの[LSON] .siz + T [rson] .siz + T [X] .D。 T [X] .SUM = T [LSON] .SUM + T [rson] .SUM + T [X] .val。 } インラインボイドマーク(INT X、LL V) { T [X] .val + = 1LL * T [X] .D * V。 T [X] .SUM + = 1LL * T [X] .siz * V。 T [X] .lazy + = V。 } インラインボイドプッシュダウン(INT X) { IF(rson)マーク(rson、T [X] .lazy)。 T [X] .lazy = 0。 } } インラインボイド回転(INT X) { int型古い= tの[X] .F、=さt(x)を取得= [古い] .Fを折ります。 T [古い] .CH [た] = tの[X] .CH [れる^ 1]、T [T [古い] .CH [れる] F =古いです。 T [X] .CH古い= [れる^ 1]、T = xと.F [古い]、T [X] .F =折ります。 IF(倍)T [倍]・CH = xで[T [1] ==古い[] .CH倍]。 腕立て伏せ(旧)、腕立て伏せ(x)は、 } インラインボイドスプレイ(INT X、INT&タール) { int型、U = T [タール] .F、V = 0。 (STA [++ V] = G、G = T [G] .F; G INT G = X)のために、 プッシュダウン(STA [i])と(; I> = 1 --I iが= V INT)のために、 (FAをint型;(FA = tの[X] .F)^ U(x)が回転する)ための (^ .F T [FA] U)の場合 ((X)を取得==)(FAを取得FA回転:X? ); タール= X; } ボイドが解決() { トップ= 0。 L [乃至[UI] = ++ティム。 T [ティム] .D = 1、T [ティム] .val =(LL)のval [UI] [します]。 } 【++トップ] =スタック(1、HD [1])、L [1] = ++ティム、T [ティム] .D = 1、T [ティム] .val =(LL)のval [1]。 (;トップ;)のために { スタックU = A [トップ]。 (UI)であれば { [トップ] .I = NEX [A [トップ] .I]。 【++トップ] =スタック([UI]に、HD [] UI [します])。 他 { R [UX] = ++ティム。 T [ティム] .D = -1、T [ティム] .val =(LL)-Val [UX]。 - 上; } } } int型のビルド(int型のL、R INT、INT FF) { int型ミッド=(L + R)>> 1。 T [中間] .F = FF。 (MID> L)Tであれば、[中間] .CH [0] =ビルド(L、ミッド- 1、MID)。 IF(R> MID)T [中間] .CH [1] =構築(MID + 1、R、MID)。 (MID == 1)T [中間] .CH [0] =ティム+ 1、T [ティム+ 1] .F =ミッド場合; (MID == TIM)T [中間]は[1] =ティム+ 2、T [ティム+ 2] .F =半ばを.CH場合。 腕立て伏せ(中旬)。 半ばを返します。 } INTプレ(INT X) { int型G =ルート; スプレイ(X、根)。 (; rson、プッシュダウン(X)、X = X = rson LSON)のために、 スプレイ(G、根)。 Xを返します。 } INT NXT(INT X) { int型G =ルート。 スプレイ(X、根)。 (; LSON、プッシュダウン(X)、X = X = LSON rson)のために、 スプレイ(G、根)。 Xを返します。 } int型のmain() { // setIO( "入力")。 INTのN、M、I、J、X、Y。 scanf関数( "%のD"、&N); 以下のための(I = 2; iが<= N; ++ I)のscanf( "%d個"、&x)は、addedge(X、I)。 用(i = 1; iは= N <; ++ I)のscanf( "%dを" &ヴァル[I])。 ()、ルート=ビルド(1、ティム、0)を解きます。 scanf関数( "%のD"、&M)。 用(int型CAS = 1; CAS <= M; ++ CAS) { 文字列str [4]。 scanf関数( "%sの"、STR)。 (STR [0] == 'Q')なら 、{ T -のscanf( "%dの"、およびX)、スプレイ(L [x]は、根)のprintf( "%LLDする\ n"、T [ルート] .SUM [T [ルート] .CH [1]の合計)。 } (STR [0] == 'C')であれば { scanf関数( "%D%dの"、およびX&Y)。 INT 1 =プレ(L [X])、R = NXT(R [X])、キー、K。 スプレイ(L、根)、スプレイ(R、T [ルート] .CH [1])、キー= tの[T [ルート] 1] [.CH]をch [0]。 Tは、[キー] .F = T [T [ルート] [1]・CH]をch [0] = 0、押し上げ(T [ルート] [1]・CH)、押し上げ(ルート)。 スプレイ(L [Y]、根)、スプレイ(NXT(L [Y])、T [ルート] .CH [1])。 T [T [ルート] .CH [1]。をch [0] =キー、T [キー] .F = T [ルート] .CH [1]、押し上げ(T [ルート] .CH [1])、突き上げ(ルート)。 } (STR [0] == 'F')であれば { scanf関数( "%D%dの"、およびX&Y)。 スプレイ(プレ(L [X])、根)、スプレイ(NXT(R [X])、T [ルート] .CH [1])。 。INTキー= tの[T [ルート] .CH [1]をCH [0]。 マーク(キー、1LLの*のY)。 } } 0を返します。 }
再帰:
#include <cstdioを> する#include <アルゴリズム> の#define N 200005 の#defineっ長い長 の#define LSONのT [X] .CH [0] の#define rson T [X] .CH [1] の#define setIO(S)freopenは(S ".IN"、 "R"、STDIN) 名前空間stdを使用。 INTエッジ、ティム、ルート= 0。 INT STA [N]、HDに[N]、[N]、NEX [N]、L [N]、R [N]、オイラー[N]、ヴァル[N]。 インラインボイドaddedge(INT U、V INT) { NEX [++エッジ] = HD [U]、HD [U] =縁、[エッジ]へ= V。 } 構造体ノード { int型SIZ、D、CH [2]、F。 LLの合計値、ヴァル、怠惰。 } T [N]。 インラインINT GET(int型X) { Tを返す[T [X] .F] .CH [1] == X。 } インラインボイド押し上げ(INT X) { T [X] .siz = tの[LSON] .siz + T [rson] .siz + T [X] .D。 T [X] .SUM = T [LSON] .SUM + T [rson] .SUM + T [X] .val。 } インラインボイドマーク(INT X、LL V) { T [X] .val + = 1LL * T [X] .D * V。 T [X] .SUM + = 1LL * T [X] .siz * V。 T [X] .lazy + = V。 } インラインボイドプッシュダウン(INT X) { IF(T [X] .lazy) { IF(LSON)マーク(LSON、T [X] .lazy)。 IF(rson)マーク(rson、T [X] .lazy)。 T [X] .lazy = 0。 } } インラインボイド回転(INT X) { =さt(x)を取得= [古い] .Fを折る、[X] .F古い= tをint型。 T [古い] .CH [た] = tの[X] .CH [れる^ 1]、T [T [古い] .CH [れる] F =古いです。 T [X] .CH古い= [れる^ 1]、T = xと.F [古い]、T [X] .F =折ります。 IF(倍)T [倍]・CH = xで[T [1] ==古い[] .CH倍]。 腕立て伏せ(旧)、腕立て伏せ(x)は、 } インラインボイドスプレイ(INT X、INT&タール) { int型、U = T [タール] .F、V = 0。 (STA [++ V] = G、G = T [G] .F; G INT G = X)のために、 プッシュダウン(STA [i])と(; I> = 1 --I iが= V INT)のために、 (FAをint型;(FA = tの[X] .F)^ U(x)が回転する)ための (^ .F T [FA] U)の場合 ((X)を取得==)(FAを取得FA回転:X? ); タール= X; } ボイドDFS(UをINT) { L [U] = ++ティム。 T [ティム] .D = 1、T [ティム] .val =(LL)のval [U]。 以下のために(INT I = HD [U]; I; I = NEX [i])とDFS(の[I])。 R [U] = ++ティム。 T [ティム] .D = -1、T [ティム] .val =(LL)-Val [U]。 } INTビルド(int型のL、R INT、INT FF) { int型ミッド=(L + R)>> 1。 T [中間] .F = FF。 (MID> L)Tであれば、[中間] .CH [0] =ビルド(L、ミッド- 1、MID)。 IF(R> MID)T [中間] .CH [1] =構築(MID + 1、R、MID)。 (MID == 1)T [中間] .CH [0] =ティム+ 1、T [ティム+ 1] .F =ミッド場合; (MID == TIM)T [中間]は[1] =ティム+ 2、T [ティム+ 2] .F =半ばを.CH場合。 腕立て伏せ(中旬)。 //のprintf( "%D%D%D \ n"は、半ば、T [中間] .CH [0]、T [中間]は.CH [1])。 半ばを返します。 } int型のプレ(INT X) { int型G =ルート。 スプレイ(X、根)。 (; rson、プッシュダウン(X)、X = X = rson LSON)のために、 スプレイ(G、根)。 Xを返します。 } INT NXT(INT X) { int型G =ルート。 スプレイ(X、根)。 (; LSON、プッシュダウン(X)、X = X = LSON rson)のために、 スプレイ(G、根)。 Xを返します。 } int型のmain() { // setIO( "入力")。 INTのN、M、I、J、X、Y。 scanf関数( "%のD"、&N); ための式(I = 2; iが<= N; ++ I)のscanf( "%d個"、&x)は、addedge(X、I)。 用(i = 1; iは= N <; ++ I)のscanf( "%dを" &ヴァル[I])。 DFS(1)、ルート=ビルド(1、ティム、0); scanf関数( "%のD"、&M)。 用(int型CAS = 1; CAS <= M; ++ CAS) { 文字列str [4]。 scanf関数( "%sの"、STR)。 IF(STR [0] == 'Q') { T -のscanf( "%dの"、およびX)、スプレイ(L [x]は、根)のprintf( "%LLDする\ n"、T [ルート] .SUM [T [ルート] .CH [1]の合計)。 } (STR [0] == 'C')であれば { scanf関数( "%D%dの"、およびX&Y)。 スプレイ(L、根)、スプレイ(R、T [ルート] .CH [1])、キー= tの[T [ルート] 1] [.CH]をch [0]。 Tは、[キー] .F = T [T [ルート] [1]・CH]をch [0] = 0、押し上げ(T [ルート] [1]・CH)、押し上げ(ルート)。 スプレイ(L [Y]、根)、スプレイ(NXT(L [Y])、T [ルート] .CH [1])。 T [T [ルート] .CH [1]。をch [0] =キー、T [キー] .F = T [ルート] .CH [1]、押し上げ(T [ルート] .CH [1])、突き上げ(ルート)。 } 場合(STR [0] == 'F') { scanf関数( "%D%dの"、およびX&Y)。 スプレイ(プレ(L [X])、根)、スプレイ(NXT(R [X])、T [ルート]。 。INTキー= tの[T [ルート] .CH [1]をCH [0]。 マーク(キー、1LLの*のY)。 } } 0を返します。 }