ZZます。https://www.cnblogs.com/cjoierljl/p/9567859.html
https://www.cnblogs.com/peng-ym/p/9357220.html
N Mの動作のセット
操作:
1 AB&マージ、セットB
バックK 2 K番目の動作後の状態(クエリカウント動作)
3 ABは、同じセットに属する、Bを尋ねるが、そうでなければ出力される出力します0
0 <N、M <= 2×10 ^ 4
サンプル入力
5 6
1 2
3 1 2
2 0
3 1 2
2 1
3 1 2
サンプル出力
1
0
1
書式#include <iostreamの> の#include <cstdlib> 書式#include <cstdioを> する#include <cmath> の#include <CStringの> の#include <iomanip> 書式#include <アルゴリズム> 書式#include <ctimeの> の#include <キュー> の#include <スタック> #include <ベクトル> の#define LST長い長 の#define LDB長い二 の#define N 200050 の#define LSON LJL [今] .ls の#define rson LJL [今] .RS 名前空間stdを使用。 const int型Infに= 1E9; INTはREAD() { int型、S = 0、M = 0; CHAR CH = GETCHAR()。 一方、(CH < '0' || CH> '9'){IF(CH == ' - ')、M = 1、CH = GETCHAR();} 一方(CH> = '0' && CH <=」9' )、S =(S << 3)+(S << 1)+(CH ^ 48)、CH = GETCHAR()。 ?リターンメートル-s:秒; } N-INT、Q、TOTは、 INT DEP [N * 30]、FA [N * 30]; int型エディ[N]; //バージョン番号の 構造体{TREE LS INT、RS;} LJL [N * 30]; //社長のツリー部 のボイドビルド(今INT&ルはint、int型RI) { IF(今!)今TOT = ++; IF(ル== RI) { FA [今] =ル; リターン; } //互いに素セット初期化 。; MID =(ル+ RI)>> 1のint ビルド(LSON、ル、MID); ビルド(rson、MID + 1、RI); } 更新(INT&今、int型の前、int型ル、int型RI、int型が無効LOC、int型FF) エンドポイントに関する//現在のバージョン、以前のバージョン(使用にコピーする)、LOCの父FFに { 今TOT = ++; //新しくオープンしたログ・ノード (ル==里場合) { DEP [今] DEP = [事前]; //バージョンが前方から来るので、そう木の深さが継承すべきである [今] = FF FAと、リターン 。 } //オーバー木"コピー"の前に置く。LSON = LJL .lsは、rson = LJL .RS【中古】【中古】 INT = MID(ル+ RI)>> 1; IF(LOC <= MID) を更新( LSON、LJL [事前] .lsル、MID、LOC、FF); 他の 更新(rson、LJL [事前] .RS、MID + 1、RI、LOC、FF); } int型クエリ(今INT、INTル、RIはint、int型LOC) FA {//クエリノードレコード[]見つける IF(LE == RI) リターン今; INT = MID(LE + RI)>> 1; IF(LOC <= MID) 戻りクエリ(LSON、ル、MID、LOC); 他の リターンクエリ(rson、MID + 1、RI、LOC。); } //ああ、永続性チェックに属し、特別なセクション設定 今のボイドアドオン(int型、int型ルを 、 RIはint、int型LOC) {ランクを変更することで//マージされた樹高 IF(ル== RI) { DEP [今] ++; リターン; } int型半ば=(LE + RI)>> 1。 もし(LOC <= MID) (LSON、ル、ミッド、LOC)を追加します。 他の アドオン(rson、ミッド+ 1、RI、LOC)。 } INT Find_fa(int型のEDI、今INT) { int型FF =クエリ(EDI、1、nは、今); //查询在这一版本里今的父亲 (今== FA [FF])であれば 、戻りFF。 リターンFind_fa(EDI、FA [FF]); //无路径压缩 } INT)(主 { N =(読み取り)、Q = read()は、 ビルド(EDI [0]、1、N) 用(INT iは= 1; I <= Q; ++ I) { int型OPT =読み取ります()。 (OPT == 1)であれば { エディ[I] =エディ[I-1]; INT X =読み取る()、Y =読み取り(); INT FX = Find_fa(EDI [I]、X)、FY = Find_fa(EDI [i]は、Y); IF(FA [FX] == FA [FY])続けます。 IF(DEP [FX]> DEP [FY]) スワップ(FX、FY); //按秩合并、把X往Y合并(DEP小的往大的合并) 更新(EDI [i]は、エディ[1- 1]、1、nは、FA [FX]、FA [FY])。 IF(DEP [FX] +1> DEP [FY]) (EDI [i]は、1、nは、FA [FY])を加えます。 } IF(OPT == 2) { int型KK =読み取ります()。 EDI [I] = EDI [KK]。 } IF(OPT == 3) { エディ[I] =エディ[I-1]; INT X =読み取る()、Y =読み取り(); INT FX = Find_fa(EDI [I]、X)、FY = Find_fa(EDI [i]は、Y); IF(FA [FX] == FA [FY]) プット( "1")。 他 プット( "0"); } } 0を返します。 }