メモリ変数の構造は、実際の速度を改善するように見えるので、データ構造を書き込んだ後
コード:
#include <cstdioを> する#include <アルゴリズム> の#include <CStringの> に#define N 200003 の#define INF 100000 の#defineっ長い長 の#define LSON Tが[X] .CH [0] の#define rson T [X] .CH [ 1] の#define setIO(S)freopenは(S ".IN"、 "R"、STDIN) 名前空間stdを使用。 INT STA [N]、N。 構造体ノード { INT CH [2]、F、SIZ、REV。 ヴァル、合計、MUL、最小、最大LL; } T [N << 1]。 インラインINT GET(INT X) { [T [X] .F] .CH [1] == X Tを返します。 } インラインINT ISRT(INT X) { リターン(!(T [T [X] .F] .CH [0] == X || T [T [X] .F] .CH [1] == x)は)|| (!バツ); } インラインボイドmark_rev(INT X) { スワップ(LSON、rson)、T [X] .rev ^ = 1; } インラインボイドmark_mul(INT X、LLのY) { T [X] .SUM * = Y、T [X] .val * = Y、T [X] .mul * = Y。 T [X] .min * = Y、T [X] .MAX * = Y、スワップ(T [X] .min、T [X] .MAX)。 } インラインボイドプッシュダウン(INT X) { IF(T [X] .rev) { IF(LSON)mark_rev(LSON)。 IF(rson)mark_rev(rson)。 T [X] .rev = 0。 } IF(!T [X] .mul = 1) { IF(LSON)mark_mul(LSON、T [X] .mul)。 IF(rson)mark_mul(rson、T [X] .mul)。 T [X] .mul = 1。 } } インラインボイド押し上げ(INT X) { T [X] .siz = T [LSON] .siz + T [rson] .siz + 1。 T [X] .SUM = T [LSON] .SUM + T [rson] .SUM + T [X] .val。 T [X] .MAX = MAX(T [LSON] .MAX、T [rson] .MAX)。 T [X] .min =分(T [LSON] .min、T [rson] .min)。 (X> N)であれば { T [X] .MAX = MAX(T [X] .MAX、T [X] .val)。 T [X] .min =分(T [X] .min、T [X] .val)。 } } インラインボイド回転(INT X) { int型古い= tの[X] .F、=さt(x)を取得= [古い] .Fを折ります。 (!ISRT(旧))であればT [倍] .CH = xの[T [1] ==古い[] .CH倍]。 腕立て伏せ(旧)、腕立て伏せ(x)は、 } T [古い] .CH [た] = tの[X] .CH [れる^ 1]、T [T [古い] .CH [れる] F =古いです。 T [X] .CH古い= [れる^ 1]、T = xと.F [古い]、T [X] .F =折ります。 インラインボイドスプレイ(INT X) { int型のV = 0、U = X、I。 用(STA [++ V] = U;!ISRT(U); STA [++ V] = tの[U] .F、U = T [U] .F)。 用(U = T [U] .F、I = V; I; - I)プッシュダウン(STA [I])。 (FAをint型;(FA = tの[X] .F)^ U(x)が回転する)ための (^ .F T [FA] U)の場合 ((X)を取得==)(FAを取得FA回転:X? ); } インラインボイドアクセス(INT X) { int型のY = 0。 一方、(X) { スプレイ(X)、rson = Y、押し上げ(X)、Y = X、X = T [X] .F。 } } インラインボイドmakeroot(INT X) { アクセス(X)、スプレイ(X)、mark_rev(X)。 } インラインボイドスプリット(int型のx、int型のY) { makeroot(X)、アクセス(Y)、スプレイ(Y)。 } インラインボイドリンク(int型のx、int型のY) { makeroot(x)は、T [X] .F = Y。 } int型のmain() { int型I、J。 scanf関数( "%のD"、&N); 用(i = 0; iがN <; ++ I)T [i]は.mul = 1。 用(i = 0; iが<= N; ++ i)はT [i]は.min = INF、T [i]は.MAX = -INF。 用(i = 1; iがn <; ++ I) { U、V、C int型。 scanf関数( "%D%D%D"、&U&V、&C)。 ++ U、V ++; T .val =(LL)C、押し上げ(iは+ N)、リンク(uは、iがN +)、リンク[iがN +(I + N、V)。 } INT T、X、Y。 文字列str [9]。 scanf関数( "%のD"、&T)。 (INT CAS = 1; CAS <= T; ++ CAS)のために { scanf関数( "%sの%D%D"、STR、およびX&Y)。 IF(STR [1] == 'I')スプリット(X + 1、Y + 1)のprintf( "%LLDする\ n"、T [Y + 1] .min)。 IF(STR [1] == 'A')スプリット(X + 1、Y + 1)のprintf( "%LLDする\ n"、T [Y + 1] .MAX)。 IF(STR [0] == 'S')スプリット(X + 1、Y + 1)のprintf( "%LLDする\ n"、T [Y + 1] .SUM)。 IF(STR [0] == 'N')スプリット(X + 1、Y + 1)、mark_mul(Y + 1、-1)。 IF(STR [0] == 'C')makeroot(X + N)、T [X + N] .val =(LL)Y、押し上げ(X + N)。 } 0を返します。 }