乗算コードを理解していない今日はそれを学ばなければなりませんでした
最初の
定義を掛けたが二回倍増されます。たとえば、あなたは毎回Fangbu K 2をジャンプすることができます。今、あなたは、ステップ7に場所からジャンプする必要があります。
ジャンプの上に8ステップ(ジャンプしません)
図4は、ステップジャンプ(ジャンプ)ジャンプしませんでした
図2は、ステップジャンプ(ジャンプ)ジャンプしませんでした
ステップ1ジャンプジャンプ(停止)
ここでは3つのだけ、通常の7つの最適化のジャンプ中に達成さ4倍に跳ね上がりました。
差が大きいデータのO(n)とがある場合にO(LOGN)。
ここでは主にRMQとLCAについての簡単なアルゴリズムの2種類があり
RMQ:両極端の範囲を検索するだけでなく、最適化されました
-
プリコード次のように
F iは2の区間長j番目のパワーの出発点として平均アレイが極値の数であります
ST(INT n)を無効///前処理
{
ため(INTはI = 1; Iは<= N-; Iを++)
; ///それらの出発点02に初期化さFは、[I]は[0] [I]は=電源は、それらの長い間隔で
((int型のJ = 1 1 << J)<= nであり、j ++)/// インターバル長列挙
{
用(INT I = 1; I +(1 << J)-1 <= N; iが++)///列挙原点
[I] [J] = F MAX([I]、[J-1] F [I(1 <<(j-1)+ F)] [J-1 ;])
}
}
何シミュレート:我々は、Fを取得する[1] [1] fであることができる[1] [0]、F [2] [0] Fを得た[1] [2] Fとすることができる[1] [1]およびF [3] [1]で得られました。我々は、大セル間の間隔、したがって実施例8に必要な時間間隔の大きさを得るため、セクションを処理するので、サイズ4れています次のように極端な値を照会
RMQ INT(INT L、R&LT INT)
{
int型K = TRUNC(IOG2(L-R&LT + 1)); ///は切り捨て
のprintf( "K D =%\ N-"、K);
戻りMAX(F [L] [K]、F [K])[R- + +1(<< 1 K)];
}
K 2は、少し遊び間隔は、長さ5を見つけるように、間隔を照会する必要があるかもしれない小さなカバーにコードを見つけることです範囲は、我々は完全にクエリの範囲をカバーして長さ4の2つのセクションを見つけます。これは、実施例124のために1-7内のすべての数の任意の組み合わせであってもよいができる理由は、このアルゴリズムが存在してもよくなり、この特性です。1の#include <iostreamの> 2の#include <cmath> 3の#include <cstdioを> 4 使って 名前空間STDを、 5 INT [ 2000010 ]。 6 INT [F 2000010 ] [ 21 ]。 7 INT RMQ(INT L、INT R) 8 { 9 int型 K = TRUNC(LOG2(R-L + 1 ))。 10 リターン分(F [L] [K]、F [R-(1 << K)+ 1 ] [K])。 11 } 12 のint main()の 13 { 14 int型N、M。 15 CIN >> N >> M。 16 のために(int型 i = 1 ; iが<= N; iが++ ) 17 のscanf(" %dの"、および[I])。 18 のためには、(int型 i = 1 ; iが<= N iが++ ) 19 F [i]が[ 0 ] = [I]を、 20 のために(INT J = 1 ;(1 << J)<= nであり、j ++ ) 21 のための(INT I = 1; I +(1 << J) - 1 <= N; iは++ ) 22 F [I] [J] =分(F [I] [J- 1 ]、F [I +(1 <<(J- 1)) ] [J- 1 ])。 23 裁判所未満<< " 0 " << てendl; 24 のためには、(int型 = Iを2 ; iがN = <; I ++ ) 25 のprintf(" %Dを\ n "、RMQ(MAX(1、IM)、I- 1 ))。 26 }
- LCA:最近の共通の祖先
共通の祖先を見つけることが最短経路を見つけることもあるため、LCA(共通の祖先)はまた、木に最短経路を見つけることを考えることができ、ルートノードに、すべてのノードからDIS []配列表現を維持し、uが最短でV距離は、[V]は-2dis DIS [U] + DIS [LCA(U、V)]です。
このアルゴリズムは、さまざまなアイデアを使用して、この位置は、最近の公共の祖先をステップを取ることで、uとv異なる祖先最初の位置を見つけることです。
しかし、uとvは確かではない、すべてのすべてのノードのDFS深さを追求する必要が同じ深さではありません
DFSは、ルート検索から始まる、状況に応じて、このツリーのルートを見つける必要があることに注意してください
どのように自分のマーク列がそれを扱う開くために、ルートノードを見つけるために!
DFSボイド(U INT)
{
(INT I = 0 I ++は; IはG [U]を.size()<)のために
{
INT = V G [U] [I];
IF(VIS [V] == 0)
{
VIS [V] = 1; ///符号
ディープ[V] =ディープ[U] + +1、
DFS(V);
}
}
}
次に、事前乗算は先祖上記2の各ノードk乗するために行われますノードとは何ですか
ST(INT n)を無効/// iがノード手順上方に1 << J乗算ノードを治療前
{
ために(J = INT 1;(1 << J)<= N; J ++)
。ための(INT I = 1; I <= N-; I ++は)
F [I] [J] = F [F [I]、[J-1]] [J-1];
}
[0] [i]のことをFを置く時の入力側に注意してください[I] [0]上記何0番目の祖先ノード2を表し、Fは良い初期化は、入力が良く初期化することは非常に容易である場合ということです。
例えば
F [1] [0] = 0はない祖先ノードが1つのルートでないことを示し
、F [2] [0] = 1 祖先ノード番号2を示す
[4] [0] = Fこのプッシュ内 2のF [5 ] [0] = 2のF [3] [0] = 1
[0] [0] fが処理される[4] [1]場合缶[F [4 F]を介して
F [4] [0] = 2 [4] [1] = Fように [2] [0] Fを私は2回ジャンプすることができる上記手段の2つのノードにノード上記と同様、4つのノード1つのノードジャンプすることによって得ることができます2つのノードが得られます。
準備作業が行われた後、共通の祖先の任意の2点は非常に効率的なクエリすることができ
LCAのINT(V int型UをINT)
{
(ディープ[U] <ディープ[V])U ///デフォルト簡略化深さの背後に大きなIF
スワップ(U、V);
int型ディープH = [U] -深い[V]、決定///高さの差
のために(0 = I int型、iが 20 <; iは++)/// この操作は、uは高さを持ち上げる任意のノードまでで感じることができるそれ自身を必要とするどのようなプロセスをシミュレートすることが困難
{
IF (H&(1 << I) )ホイスト1上/// 1ビットの2ステップの存在に生成<< I
{
U = F [U] [I];
}
}
IF(U == V)///場合Uはuが== Vが表すV下部ブランチノードである
Uを返す。
ため(INT I = 19; I> = 0; I - )///ない最初は、同じノードを見つけるために、
{
IF(F [U] [ !I] = F [v] [i])と/// 又は124の使用は、工程1-7の全ての数の任意の組み合わせとすることができる
{
U = F [U] [I];
V = F [V] [ I];
}
}
戻りF [U] [0]; ///異なる第1のノードに共通の祖先です
}