予備知識:バイナリヒープ
まず、我々は定義 外部ノードを 左または右の息子の息子の空のノードへの定義外のノード DISTが ゼロである、空のノード DISTは -1であり、距離がそのサブツリー内のDISTの他のノードに最も近いノード外側プラスA。
だから、左側のツリーは何ですか?左翼ツリーはある二分木有するだけでなく、ヒープの性質を、そしてある「左側」:DIST左各ノード息子 DISTの右息子に等しいより大きい 、加えて、右の各ノードDISTのDISTの息子1。
左側は、ツリーで積み重ねることができ、以下のコードを参照の合成プロセス:
#define LSのS [X] .son [0] の#define RSのS [X] .son [1] 構造体ノード{ INT DIS、ヴァル、息子[ 2 ]、RT; } S [ 150010 ]; int型のマージ(INT X 、INT Yは){ // これは合成小スタックのルートである IF !!(X || Y)を返す X + Yであり; // 別のスタックリターンヌルにスタック IF [(S [X] .val> S Y] .val ||(S [X] .val == S [Y] .val && X> Y))スワップ(X、Y); // 細根がスタックので、前述のように小さな値 RS =マージ(RS、Y); // 置くX、ルートYの右息子のルートとして再帰ためバイナリヒープの性質を満たすために別の小さな組み合わせるように IF(S [LS] .DIS <S [RS] .DIS )スワップ(LS、RS); //自然が右側よりも彼の息子の息子のdist distの方が大きい満たすために残されているので =のS .rt S [LS] X-S = [X-] [RS] .rt = .rt; // 息子と父親の周りの根自体が設定されていますルート自体 S [X] = Sが.DIS [RS] + .DIS 1。 ; // 右の子として定義されたルートDISTのDIST 1 + DIST; リターン X; // 新しいルートを返します }
スタックのスタックトップをさらに見つけるすなわち、互いに素なセットパス圧縮最適化することができます。
INT GET(INT X){ // 互いに素なセット圧縮パス IF(S [X] .rt == X)リターンX、 S [X] .rt = GET (S [X] .rt); 戻りSを[ X] .rt; }
あなたはポイントを削除する場合:
ボイド POP(INT X){ S [X] .val = - 1 ; // 穿刺点は-1に自分の体重である =の.rt S [LS] LS、 S [RS] .rt = RS; / / 彼の息子の父親についての彼の息子についての自分自身を設定する S [X-]は.rt =(LS、RS)をマージ; // 直前に削除したため、新しいルート(に削除されたポイントをマージの原点を削除し、彼の息子についての彼の父を覚えています二つにスタックをしないポイント) }
だから、この質問は、コードから出てきました:
#include <ビット/ STDC ++ H> の#define LSのS [X] .son [0] の#defineのRS S [X] .son [1] 使用 名前空間STDを、 int型、N、T、A、B、C。 構造体ノード{ INT DIS、ヴァル、息子[ 2 ]、RT。 } S [ 150010 ]。 INTのマージ(int型のx、int型のY){ 場合(!X || Y)リターン X + Y。 もし(S [X] .val> S [Y] .val ||(S [X] .val == S [Y] .val && X> Y))スワップ(X、Y) RS = マージ(RS、Y)。 もし(S [LS] .DIS < S [RS] .DIS)スワップ(LS、RS)。 S [LS] .rt = S [RS] .rt = S [X] .rt =バツ; S [X] .DISの = S [RS] .DIS + 1 。 リターンのx; } INT GET(INT X){ もし、(S [X] .rt == x)をリターンX。 S [X] .rt = GET (S [X] .rt)。 リターンS [X] .rt。 } ボイドポップ(INT X){ S [X] .val = - 1 。 .rt S [LS] =のLS。 S [RS] .rt = RS。 S [X] .rt = マージ(LS、RS)。 } int型のmain(){ CIN >> N >> T。 S [ 0 ] = .DIS - 1 。 以下のために(int型 iは= 1 ; iがn = <; iは++ ){ S [i]は.rt = I。 scanf関数(" %のD "、&S [I] .val)。 } のために(int型 I = 1 ; I <= T; iは++ ){ scanf関数(" %d個の%のD "、&、&B)。 もし(== 1 ){ scanf関数(" %のD "、&C)。 もし(S [B] .val == - 1つの || S [C] .val == - 1)続けます。 int型 B = 取得(B)、C = GET (C); もし(!B = C){ S [B] .rt = S [C] .rt = マージ(B、C)。 } } 他{ もし、(Sは[B] .val == - 1)のprintf(" -1の\ n " ); 他のprintf(" %dは\ nを"、S [ 取得。(B)] val)で、ポップは(取得(b)参照)。 } } 戻り 0; }
いくつかの質問をお勧めしますか?
羅区1456猿の王
羅区2713回のローマ大会
また、それは聞くことができるとヒープは#で、STLを持っている