抜粋:https://www.cnblogs.com/mjtcn/p/8028926.html%グレート神
テキスト
FHQ treap仕上げ
treap =ツリー+ヒープ、すなわち、特性を満足しながら、二分探索木とヒープ。
木の両側極力ので、彼は木のバランスを維持するために、積み重ね自然を満たすように、キーの値があるバランスの大きさは、キー値がランダムであることを確実にするために。
treapバランスの取れたツリーは、前駆体の一般的な機能、後継者を持って、k番目のランク付け、最大のクエリ、挿入、削除。また、より良い書き込みするの
しかし、問題の間隔は、たとえば、実行することはできません、
- 間隔を短く
- インターバル最も値
- 間隔反転(リバース)
- 可動部(セクションカットアンドペースト)
(行うことができますスプレイ)
-しかし、魔法のデータ構造が存在する、すなわち、treap機能も間隔で動作することができる満たすFHQ treap
コードの量もはるかに小さいのでFHQは、2つだけの基本的な操作をtreap。
スプリット
二つに分離treapのtreapを話します。
分離の2つのタイプが1より大きい、以下Kに、重量ヴァルポイントに応じて、存在しています。もう一つは、除去前部分にkの数です。
重量:
分割ツリーを再構築するときにそのようTreapため、以下、K点は、サブツリー内に存在するが、kのZhekeサブツリーより大きい有していてもよいです。
(今INT、int型K、INT&X、INT&Y)1つの空隙分割{ 2であればX = Y = 0(今!)。 3そう{ 4もし(ヴァル[今] <= K) 5×=今、スプリット(CH [今] [1]、K、CH [今] [1]、Y)。 他の6 7 Y =今、スプリット(CH [今] [0]、K、X、CH [今] [0])。 8押し上げ(今)。 9} 10}
コードは、それは、2つの値、X、Yを指し、非常に素晴らしいです、これら2つの値は、二つの変数の復興の中で最も重要であり、アドレスの文字を取らなければなりません。
xは基準ノードK以下(仮定)、右の息子は、yは基準ノードが息子kを放置するよりも大きいです。
kは以下であり、その左部分木は、右の子k個以下であるが、必ずしもkより小さくない場合、ので、ここでそれが適切な息子を取られ、第一のノードに遭遇したときはK未満です、それは右の息子であるとします。
図は、右の子が適切な息子が変化するように、次の工程は、右子を左に行くために、6よりも大きいことが見出され、K = 6、その後、6未満であり、右に移動し、次6の重量にポイント。
復興プロセス:値は、彼はいくつかは、k個未満の左、右のように行っていた今現在のポイントkよりも小さい場合。
複雑さ O (L O GのN- ) O(logN個)
フロントセクション番号k
(今INT、int型K、INT&X、INT&Y)1つの空隙分割{ 2であればX = Y = 0(今!)。 他の3 { 4もし(K <= SIZ [CH [今] [0]]) 5 Y =今、スプリット(CH [今] [0]、K、X、CH [今] [0])。 他の6 7 X =今、スプリット(CH [今] [1]、K-SIZ [CH [今] [0]] - 1、CH [今] [1]、Y)。 8押し上げ(今)。 9} 10}
原理は詳細に説明されていない、同じです。
複雑、O (L O GのN- ) O(logN個)
マージ
すべてのツリーノードの重みの全ての点が第サブツリーの粒子よりも小さいことを保証する合成二サブツリー。
そして、十分なヒープの性質限り、再構築します。
2変数x、yがあり、
1つのINTマージ(int型のx、int型のY){ 2であればリターンX + Y(X || Y!)。 3 IF(キー[X] <キー[Y]){ 4個のCH [X] [1] =マージ(CH [X] [1]、Y)。 5押し上げ(X)。Xを返します。 6} そう7 { 8 CH [Y] [0] =マージ(X、CH [Y] [0])。 9押し上げ(Y)。Yを返します。 10} 11}
ここでは、xツリーキー時間は、xの左半分のみがツリーの復興に添加した場合に、yのサブツリー時間は、それが唯一のサブツリーの右半分に追加ことがわかります。自然のtreapを満たすために。
複雑さ O (L O GのN- ) O(logN個)
二つの基本的な操作は完了です。
インサート
重み値kの数を挿入します。
プロセス:未満またはKに等しい2つにtreap、kはXよりも大きいと、2つのサブツリーを組み合わせることができます
スプリット(ルート、K、X、Y)。 ルート=併合(マージ(X、MAKENODE(k))を、Y);
削除
数kの値を削除する権利。
プロセス:最初未満またはKより大きい等しいk個に分割し、B、次いでK-1にxまたは以下CとDは、K-1よりも大きい場合、kはDであり、それは二人の息子dをマージし、次いでC、Bを組み合わせることができます。
スプリット(ルート、X、Y) スプリット(X-1、X、Z)。 Z =マージ(CH [I] [0]、B [i]を[1])。 ルート=併合(マージ(X、Z)、S);
Kランキング
Kは、ランキングを求めています
手順:K-1 X以下に等しく、K-1、Y 2つのサブツリーを超えるに、xはランクkのサブツリーの大きさです。
スプリット(ルート、K-1、x、y)は、 printf( "%d個の\ n"、SIZ [X] +1)。 ルート=(x、y)をマージします。
最初の数k
kの数を求めて
プロセス:決意とスプレイ、treap等。
インラインINT getkth(INT P、INT K){ 一方(TRUE){ IF(K == SIZ [CH [P] [0] + 1)リターンP。 IF(CH [P] [0] && K <= SIZ [CH [P] [0]])P = CH [P] [0]。 他K- =(?(CH [P] [0] SIZ [CH [P] [0]:0)+ 1)、P = CH [P] [1]。 } }
前駆
Kは、ランキングを求めています
手順:K-1 X以下に等しく、K-1、Y 2つのサブツリーを超えるに、Xサブツリーは、最大数x前駆体です。
スプリット(ルート、K-1、x、y)は、 printf( "%d個の\ n"、ヴァル[getkth(X、SIZ [X])])。 ルート=(x、y)をマージします。
後継者
Kは、ランキングを求めています
プロセス:Xに少ないK、およびy kは2つのサブツリーのサブツリーY xは前駆体の最小数よりも大きいです。
スプリット(ルート、K、X、Y)。 printf( "%d個の\ n"、ヴァル[getkth(Y、1)])。 ルート=(x、y)をマージします。
基本的な操作は、これらがFHQtreapであるということです