コード:
書式#include <cstdioを> する#include <アルゴリズム> 書式#include <cmath> 名前空間stdを使用。 #define LS LSON [X] の#defineのRS rson [X] の#define setIO(S)freopenは(S ".IN"、 "R"、STDIN)、freopenは(S ".out"を、 "W"、STDOUT) CONST int型MAXN = 500000; const int型N = 1000000000; 名前空間IO { チャー*のP1、P2 *、BUF [100000]。 #define NC()(P1、P2 == &&(P2 =(P1 = BUF)+関数fread(BUF、1,100000、STDIN)、P1 == P2)EOF:* P1 ++) int型RD(){ int型のx = 0 ; チャーC = NC()。 一方、(C <48)C = NC()。 一方、(C> 47)x =(((X << 2)+ X)<< 1)+(C ^ 48)、C = NC()。 Xを返します。 } }。 {INITを無効() [I] = iがP(++ iは; iがMAXNを<I = 0をINT)ため、 } INT(INT X){見つける ?戻りP [X] == X X:Pは[X] =(P [X])を見つけます。 } } TR。 int型のCNT; INT RT [MAXN]、LSON [MAXN * 10]、rson [MAXN * 10]、NUM [MAXN * 10]。 ダブルデ[MAXN * 10]。 int型newnode(){ リターン++ CNT。 } ボイド押し上げ(INT X){ NUM [X] = NUM [LS] + NUM [RS]。 デ[X] =デ[LS] +ド[RS]。 } ボイド更新(INT&X、int型のL、R INT、INT P、INT V){ (!x)は、x = newnode()であれば、 IF(L == R){ NUM [X] + = V、デ[X] + =(ダブル)は、V *(ダブル)(ログ(P))。 返します。 } INT半ば=(L + R)>> 1。 IF(p <= MID)更新(LS、L、中、P、V)。 他の更新(RS、ミッド+ 1、R、P、V); 突き上げ(X)。 } int型のマージ(int型のx、int型のY){ もしリターンX + Y(X || Y!)。 NUM [X] + = NUM [Y]。 デ[X] + =デ[Y]。 LSON [X] =(LSON [X]、LSON [Y])をマージします。 rson [X] =マージ(rson [X]、rson [Y])。 Xを返します。 } 以下(INT&X、int型のL、int型のR、int型K){int型 (!X || L> = k)の場合はリターン0; int型の再= 0; (R <K){もし 再= NUM [x]は、x = 0。 再を返します。 } IF(L == R)戻り0; INT半ば=(L + R)>> 1。 (LS、L、中、K)+ =少ない再。 + =以下(RS、ミッド+ 1、R、K)再。 突き上げ(X)。 再を返します。 } より大きい(INT&X、int型のL、int型のR、int型K){int型 (!X || R <= K)であれば戻り0; int型の再= 0; IF(L> K){ 再= NUM [x]は、x = 0。 再を返します。 } IF(L == R)戻り0; INT半ば=(L + R)>> 1。 + =大きく(LS、L、中、k)を再。 + =大きく(RS、ミッド+ 1、R、K)再。 突き上げ(X)。 再を返します。 } INT番目(int型のx、int型、L、のint R、int型K){ IF(L == R)戻りL。 INT半ば=(L + R)>> 1。 もし(K> NUM [LS])戻りk番目(RS、ミッド+ 1、R、K-NUM [LS])。 それ以外の戻りk番目(LS、L、ミッド、K); } メインINT(){ 使用して名前空間IO。 整数mを、CC = 0。 M = RD()。 tr.init(); 用(INT CAS = 1; CAS <= M; ++ CAS){ int型のOP = RD()。 IF(OP == 1){ int型のx = RD()。 ++ CC; アップデート(RT [CC]、1、N、X、1)。 } IF(OP == 2){ int型、X、Y、B。 X = RD()、Y = RD()。 = tr.find(X)、B = tr.find(Y)。 (!= B){場合 RT [B] =マージ(RT [A]、RT [B])。 tr.p [A] Bを=。 } } (オペアンプ== 3){もし 、X INT、C = 0。 = RD()、X = RD()。 = tr.find(A)。 C =以下(RT [A]、1、N、X)。 アップデート(RT [A]、1、N、X、C)。 } (OPの== 4){もし 、X INT、C = 0。 = RD()、X = RD()。 = tr.find(A)。 C =より大きい(RT [A]、1、N、X)。 アップデート(RT [A]、1、N、X、C)。 } (OPの== 5){もし 、K INT。 = RD()、K = RD()。 = tr.find(A)。 printf( "%d個の\ n"、k番目(RT [A]、1、N、K))。 } (オペアンプ== 6){もし 、B INT。 = RD()、B = RD()。 = tr.find(A)、B = tr.find(B)。 IF(デ[RT []]>ド[RT [B])のprintf( "1 \ n"); 他のprintf( "0 \ N"); } (OPの== 7){もし INT。 = RD()。 = tr.find(A)。 printf( "%d個の\ n"、NUM [RT [A])。 } } 0を返します。 }