ERATO若手輪読会 2014/11/19
LCA and RMQ
北海道大学大学院 情報科学研究科
博士1年 井上 祐馬
1
ERATO若手輪読会 2014/11/19
• LCA: Lowest Common Ancestor (最近共通祖先)
• 根付き木 T 上の2頂点 u, v に対するクエリ LCA(u,v)
• u と v の祖先であって、もっとも深い頂点 x を返す
• RMQ: Range Minimum Query (区間最小値)
• 列 A[1:n] 上の区間 [l, r] に対するクエリ RMQ(l,r)
• A[l:r] 中での最小値 A[i] を取るような i を返す
• LCA と RMQ には密接な関係がある
LCAとRMQ
2
u
v
x
id 1 2 3 4 5 6
A[id] 1 8 2 6 3 5
l r
i
T
ERATO若手輪読会 2014/11/19
LCAとRMQ
• クエリ処理アルゴリズムの計算量表記: <f(n), g(n)>
• f(n): 前処理時間, g(n): 1つのクエリの処理時間
3
・LCA と RMQ を <O(n), O(1)> で解く
・(時間があれば)空間 2n + o(n) bit の
 簡潔データ構造で <O(n), O(1)> で処理する
今日の目標
ERATO若手輪読会 2014/11/19
LCAとRMQ
• クエリ処理アルゴリズムの計算量表記: <f(n), g(n)>
• f(n): 前処理時間, g(n): 1つのクエリの処理時間
4
LCA を <f(n), g(n)> で解くアルゴリズムが存在

→ RMQ は <f(n)+O(n), g(n)+O(1)> で解ける
RMQ を <f(n), g(n)> で解くアルゴリズムが存在

→ LCA は <O(f(n))+O(n), O(g(n))+O(1)> で解ける
定理1
定理2
ERATO若手輪読会 2014/11/19
RMQ to LCA
5
LCA を <f(n), g(n)> で解くアルゴリズムが存在

→ RMQは <f(n)+O(n), g(n)+O(1)> で解ける
定理1
• 列Aを Cartesian Tree に変換
• Cartesian Tree
• 値の2分ヒープ構造
• 頂点ラベルはインデックス
• 子の左右が列の左右と一致 id 1 2 3 4 5 6
A[id] 1 8 2 6 3 5
1
3
2
5
4
6
ERATO若手輪読会 2014/11/19
RMQ to LCA
6
• RMQ(l,r):

Cartesian Tree上でLCA(l,r)を解く
ことで最小値インデックスが求まる

• Cartesian Treeの構築: O(n)
• 最小値そのものが知りたいとき:

メモリアクセス O(1)
id 1 2 3 4 5 6
A[id] 1 8 2 6 3 5
1
3
2
5
4
6
LCA を <f(n), g(n)> で解くアルゴリズムが存在

→ RMQは <f(n)+O(n), g(n)+O(1)> で解ける
定理1
ERATO若手輪読会 2014/11/19
LCA to RMQ
• 木 T を Euler Tour で展開
• Euler Tour:
• TをDFSで辿る
• 頂点の訪問順で列を定義
• 列の長さは必ず2n-1
7
RMQ を <f(n), g(n)> で解くアルゴリズムが存在

→ LCA は <O(f(n))+O(n), O(g(n))+O(1)> で解ける
定理2
4 65
2
1
3
T
id 1 2 3 4 5 6 7 8 9 10 11
A[id] 1 2 1 3 4 3 5 3 6 3 1
ERATO若手輪読会 2014/11/19
LCA to RMQ
• LCA(u,v):

深さ配列d上でRMQ(l,r)

(l, rはu, vのAでの出現位置)
• Euler Tourへの展開: O(n)
• LCAの頂点番号取得: 

メモリアクセス O(1)
8
RMQ を <f(n), g(n)> で解くアルゴリズムが存在

→ LCA は <O(f(n))+O(n), O(g(n))+O(1)> で解ける
定理2
4 65
2
1
3
T
id 1 2 3 4 5 6 7 8 9 10 11
A[id] 1 2 1 3 4 3 5 3 6 3 1
d[id] 0 1 0 1 2 1 2 1 2 1 0
ERATO若手輪読会 2014/11/19
LCAとRMQ
• 定理より、LCA または RMQ のどちらか一方が
<O(n), O(1)> で解ければ、もう一方も<O(n), O(1)>
• LCAとRMQには、それぞれ様々なアルゴリズムが
提案されている
9
ERATO若手輪読会 2014/11/19
RMQのアルゴリズム
10
空間 前処理 クエリ
Segment Tree
(動的)
O(n) O(n) O(log n)
Sparse Table O(n logn) O(n logn) O(1)
Cartesian Tree
+ LCA
O(n) + ? O(n) + ? O(1) + ?
※ここでは各値を表すのに必要な O(logn) は無視
ERATO若手輪読会 2014/11/19
LCAのアルゴリズム
11
空間 前処理 クエリ
Doubling O(n logn) O(n logn) O(log n)
Heavy Path
Decomposition
O(n) O(n) O(1)
Euler Tour
+ RMQ
O(n) + ? O(n) + ? O(1) + ?
※ここでは各値を表すのに必要な O(logn) は無視
ERATO若手輪読会 2014/11/19
<O(n), O(1)>アルゴリズム
• LCAはHeavy Path Decompositionを利用して、
直接 <O(n), O(1)> で解くことが可能
• ただし、簡潔化が難しい
• LCAで必要とされるRMQがある特殊な条件を満た
すことを利用して、RMQを <O(n), O(1)> で解く
12
ERATO若手輪読会 2014/11/19
1RMQ
• LCA: Euler Tour の深さ配列でRMQ
• 1回の移動で深さはちょうど1だけ変わる
• 深さ配列の隣接要素同士は+1 か -1 だけ異なる
• 隣接要素の変化が 1 である列上での RMQ を 1RMQ
と呼ぶ
• 1RMQ が <O(n), O(1)> で解ければ、LCA も <O(n),
O(1)> で解ける
134 65
2
1
3
id 1 2 3 4 5 6 7 8 9 10 11
A[id] 1 2 1 3 4 3 5 3 6 3 1
d[id] 0 1 0 1 2 1 2 1 2 1 0
+1 +1 +1 +1 +1 -1 -1-1-1-1
ERATO若手輪読会 2014/11/19
<O(n), O(1)> RMQ
RMQを <O(n), O(1)> で解く流れ
1. RMQ を Cartesian Tree に変換し、LCA に帰着

( 時間・空間: O(n) )
2. LCA を Euler Tour で展開し、 1RMQ に帰着

( 時間・空間: O(n) )
3. 1RMQ を以下のテクニックで <O(n), O(1)> で解く
• ブロック分割
• Sparse Table
• Table Lookup
14
[Bender et. al. '05]
ERATO若手輪読会 2014/11/19
ブロック分割
• 簡潔データ構造の典型テクニック
• 長さnの列を長さs = logn/2のブロックに分割
• ブロックの数 B = 2n/logn
• 各ブロックの最小値インデックスを O(n) で前計算
• 全体の RMQ クエリは、以下のクエリに分割される
• ブロックの区間に対する RMQ クエリ1回
• ブロック内部に対する RMQ クエリ2回
15
id 1 2 3 4 5 6 7 8 9 101112131415161718192021222324252627282930
A[id] 1 2 1 3 4 3 5 3 6 3 1 8 4 9 11 4 1 5 6 3 2 5 2 5 2 1 9 8 4 1
ERATO若手輪読会 2014/11/19
ブロック分割
• 簡潔データ構造の典型テクニック
• 長さnの列を長さs = logn/2のブロックに分割
• ブロックの数 B = 2n/logn
• 各ブロックの最小値インデックスを O(n) で前計算
• 全体の RMQ クエリは、以下のクエリに分割される
• ブロックの区間に対する RMQ = Sparse Table
• ブロック内部に対する RMQ = Table Lookup
16
id 1 2 3 4 5 6 7 8 9 101112131415161718192021222324252627282930
A[id] 1 2 1 3 4 3 5 3 6 3 1 8 4 9 11 4 1 5 6 3 2 5 2 5 2 1 9 8 4 1
それぞれ <O(n), O(1)> で
解ければOK
ERATO若手輪読会 2014/11/19
Sparse Table
• i 番目から長さ2kの区間の最小値インデックスをそれ
ぞれ記憶したO(n logn)のテーブルを持つ
• 構築: O(n logn)
• S[i][k+1] = argmin( A[S[i][k]], A[S[i+2k][k]] )
• クエリ: O(1)
• RMQ(i, j) = argmin( A[S[i][k]], A[S[j-2k+1][k]] )
• k = floor( log(j-i) ) ← O(1)で求められると仮定
17
id 1 2 3 4 5 6 7 8
A[id] 1 2 1 3 4 3 5 3
id 1 2 3 4 5 6 7 8
A[id] 1 2 1 3 4 3 5 3
構築: クエリ:
ERATO若手輪読会 2014/11/19
Sparse Table
• i 番目から長さ2kの区間の最小値インデックスをそれ
ぞれ記憶したO(n logn)のテーブルを持つ
• B個のブロックに対し、<O(B logB), O(1)> のアルゴ
リズム
• B = 2n/lognより、

B logB = 2n/logn・(log2n - loglogn) = O(n)
18
id 1 2 3 4 5 6 7 8
A[id] 1 2 1 3 4 3 5 3
id 1 2 3 4 5 6 7 8
A[id] 1 2 1 3 4 3 5 3
構築: クエリ:
ERATO若手輪読会 2014/11/19
Table Lookup
• 簡潔データ構造の典型テクニック その2
• 1 で変化している列の最小値インデックスは、値
そのものを見なくても変化量だけ見ればわかる
• すべての変化パターンと区間 [l,r]について、最小値
インデックスを記録して参照すればよい
• 長さ s の列の変化のパターンは2s通り
• よって、<O(s22s), O(1)> のアルゴリズム
• s = logn/2より、s22s = O(log2n n) = o(n)
19
ERATO若手輪読会 2014/11/19
<O(n), O(1)> RMQ
RMQ を <O(n), O(1)> で解けた!!!
1. RMQ を Cartesian Tree に変換し、LCA に帰着

( 時間・空間: O(n) )
2. LCA を Euler Tour で展開し、 1RMQ に帰着

( 時間・空間: O(n) )
3. 1RMQ を以下のテクニックで <O(n), O(1)> で解く
• ブロック分割
• Sparse Table
• Table Lookup
20
[Bender et. al. '05]
ERATO若手輪読会 2014/11/19
-----↓ここから簡潔↓-----
21
ERATO若手輪読会 2014/11/19
簡潔RMQ
RMQ を <O(n), O(1)> で解けた!!!
1. RMQ を Cartesian Tree に変換し、LCA に帰着

( 時間・空間: O(n) )
2. LCA を Euler Tour で展開し、 1RMQ に帰着

( 時間・空間: O(n) )
3. 1RMQ を以下のテクニックで <O(n), O(1)> で解く
• ブロック分割
• Sparse Table
• Table Lookup
22
BP (Balanced Parentheses) 表現で2n bitに
BP上の rank( - rank) が深さに対応 → Euler Tour なしに 1RMQ
分割を多段にすることで o(n) bitに
[Sadakane '07]
ERATO若手輪読会 2014/11/19
簡潔RMQ
• 問題点: BP 上でわかるのは pre-order

RMQ で求めたいインデックスは

Cartesian tree 上では in-order
• 対応を覚える場合O(n logn) bit を使う → not 簡潔
• Cartesian Tree に dummy node を n 個付加するこ
とで解決 → 4n + o(n) bitに
23
[Sadakane '07]
id 1 2 3 4 5 6
A[id] 1 8 2 6 3 5
1
3
2
5
4
6
( ( ( ) ( ( ) ( ) ) )
1
1
3
2
2
8
4
6
5
3
6
5
ERATO若手輪読会 2014/11/19
簡潔RMQ
• 問題点: BP 上でわかるのは pre-order

RMQ で求めたいインデックスは

Cartesian tree 上では in-order
• 対応を覚える場合O(n logn) bit を使う → not 簡潔
• Cartesian Tree に dummy node を n 個付加するこ
とで解決 → 4n + o(n) bitに
24
[Sadakane '07]
id 1 2 3 4 5 6
A[id] 1 8 2 6 3 5
1
3
2
5
4
6
( ( ( ) ( ( ) ( ) ) )
1
1
3
2
2
8
4
6
5
3
6
5
2n
にしたい
ERATO若手輪読会 2014/11/19
簡潔RMQ
• Cartesian Tree + BP の代わりに 2D-Min Heap +
DFUDS (Depth-First Unary Degree Sequence)
• 流れ:
• 入力列を 2D-Min Heap を表すDFUDSに変換
• O(n)時間、 DFUDSは 2n bit
• DFUDS に必要な索引を付加
• O(n)時間、索引は o(n) bit
• 索引付き DFUDS 上で LCAを解く
• 内部で rank, select, findopen, 1RMQ 等を使用
• O(1) 時間
25
[Fischer '09]
id 0 1 2 3 4 5 6
A[id] - 1 8 2 6 3 5
1
32
54
6
2D-Min Heap
0
DFUDS: ( ( ) ( ( ) ) ( ( ) ) ( ) )
ERATO若手輪読会 2014/11/19
簡潔RMQ
• Cartesian Tree + BP の代わりに 2D-Min Heap +
DFUDS (Depth-First Unary Degree Sequence)
• 2D-Min Heap:
• 自分より左かつ小さいもののうち、最も右にある
ものを親にする
26
[Fischer '09]
id 0 1 2 3 4 5 6
A[id
]
- 1 8 2 6 3 5
1
3
2 5
4 6
1
32
54
6
Cartesian Tree
2D-Min Heap
0
ERATO若手輪読会 2014/11/19
簡潔RMQ
• RMQ(i, j)は、2D-Min Heap 上では、
• LCA(i, j)が i → RMQ(i, j) = i
• それ以外 → RMQ(i, j) = LCA(i, j)の子で、jの先祖
27
[Fischer '09]
id 0 1 2 3 4 5 6
A[id
]
- 1 8 2 6 3 5
2D-Min Heap
1
32
54
6
0
i j LCA(2,4)
RMQ(2,4)
ERATO若手輪読会 2014/11/19
簡潔RMQ
• Cartesian Tree + BP の代わりに 2D-Min Heap +
DFUDS (Depth-First Unary Degree Sequence)
• DFUDS:
• 葉は ( )
• w 個の子 T1, ..., Tw の親は w+1 個の ( と 1個の ) の後、
子を続ける.ただし、子の表現は先頭の ( を1つ削る
28
[Fischer '09]
( ( ) ( ( ) ) ( ( ) ) ( ) )
id 0 1 2 3 4 5 6
d 1 2 1 2 3 2 3 4 3 4 3 2 1 0
A[id] - 1 8 2 6 3 5
1
32
54
6
0
ERATO若手輪読会 2014/11/19
• RMQ(i, j)
1. l ← select)(U, i+1), r ← select)(U, j)
2. w = 1RMQ(l, r)
3. if rank)(U, findopen(U, w)) = i, then return i
4. else rank)(U, w)
29
簡潔RMQ [Fischer '09]
U: ( ( ) ( ( ) ) ( ( ) ) ( ) )
id 0 1 2 3 4 5 6
d 1 2 1 2 3 2 1 2 3 2 1 2 1 0
A[id] - 1 8 2 6 3 5
1
32
54
6
0
i j
l r
1RMQ(l,r)
findopen
ERATO若手輪読会 2014/11/19
• RMQ(i, j)
1. l ← select)(U, i+1), r ← select)(U, j)
2. w = 1RMQ(l, r)
3. if rank)(U, findopen(U, w)) = i, then return i
4. else rank)(U, w)
30
簡潔RMQ [Fischer '09]
U: ( ( ) ( ( ) ) ( ( ) ) ( ) )
id 0 1 2 3 4 5 6
d 1 2 1 2 3 2 1 2 3 2 1 2 1 0
A[id] - 1 8 2 6 3 5
1
32
54
6
0
i j
l r
1RMQ(l,r)
findopen
DFUDS 上の RMQ では、
w は i と j のLCAの子であり、
jの祖先である
(ただし LCA が iのとき w=i )
[Jansson et. al. '07]
ERATO若手輪読会 2014/11/19
• RMQ(i, j)
1. l ← select)(U, i+1), r ← select)(U, j)
2. w = 1RMQ(l, r)
3. if rank)(U, findopen(U, w)) = i, then return i
4. else rank)(U, w)
31
簡潔RMQ [Fischer '09]
U: ( ( ) ( ( ) ) ( ( ) ) ( ) )
id 0 1 2 3 4 5 6
d 1 2 1 2 3 2 1 2 3 2 1 2 1 0
A[id] - 1 8 2 6 3 5
1
32
54
6
0
i j
l r
1RMQ(l,r)
findopen
親が preorder わかる
ERATO若手輪読会 2014/11/19
• RMQ(i, j)
1. l ← select)(U, i+1), r ← select)(U, j)
2. w = 1RMQ(l, r)
3. if rank)(U, findopen(U, w)) = i, then return i
4. else rank)(U, w)
32
簡潔RMQ [Fischer '09]
U: ( ( ) ( ( ) ) ( ( ) ) ( ) )
id 0 1 2 3 4 5 6
d 1 2 1 2 3 2 1 2 3 2 1 2 1 0
A[id] - 1 8 2 6 3 5
1
32
54
6
0
i j
l r
1RMQ(l,r)
findopen自分の preorder わかる
ERATO若手輪読会 2014/11/19
割愛したところ
• 入力列から直接 2n bit のDFUDSへ O(n) で変換
• 簡潔でない方法: スタックを利用したアルゴリズム
• 簡潔な方法: スタックを簡潔にする
• 1RMQ をより簡潔に
• o(n) で隠された部分がより succinct に
• 具体的には、(loglogn)2 かかっていたところが
loglogn に落とせる
33
ERATO若手輪読会 2014/11/19
まとめ
• LCA と RMQは適切に変換することで等価な問題
として解ける
• LCA to RMQ: Euler Tour, BP, DFUDS
• RMQ to LCA: Cartesian Tree, 2D-Min Heap
• LCA で要求される RMQ が 1RMQ であることを
利用し、<O(n), O(1)> を実現する
• 木の簡潔表現と LCA, RMQ の簡潔辞書により、
2n + o(n) bitで、<O(n), O(1)> を実現する
34

LCA and RMQ ~簡潔もあるよ!~

  • 1.
    ERATO若手輪読会 2014/11/19 LCA andRMQ 北海道大学大学院 情報科学研究科 博士1年 井上 祐馬 1
  • 2.
    ERATO若手輪読会 2014/11/19 • LCA:Lowest Common Ancestor (最近共通祖先) • 根付き木 T 上の2頂点 u, v に対するクエリ LCA(u,v) • u と v の祖先であって、もっとも深い頂点 x を返す • RMQ: Range Minimum Query (区間最小値) • 列 A[1:n] 上の区間 [l, r] に対するクエリ RMQ(l,r) • A[l:r] 中での最小値 A[i] を取るような i を返す • LCA と RMQ には密接な関係がある LCAとRMQ 2 u v x id 1 2 3 4 5 6 A[id] 1 8 2 6 3 5 l r i T
  • 3.
    ERATO若手輪読会 2014/11/19 LCAとRMQ • クエリ処理アルゴリズムの計算量表記:<f(n), g(n)> • f(n): 前処理時間, g(n): 1つのクエリの処理時間 3 ・LCA と RMQ を <O(n), O(1)> で解く ・(時間があれば)空間 2n + o(n) bit の  簡潔データ構造で <O(n), O(1)> で処理する 今日の目標
  • 4.
    ERATO若手輪読会 2014/11/19 LCAとRMQ • クエリ処理アルゴリズムの計算量表記:<f(n), g(n)> • f(n): 前処理時間, g(n): 1つのクエリの処理時間 4 LCA を <f(n), g(n)> で解くアルゴリズムが存在
 → RMQ は <f(n)+O(n), g(n)+O(1)> で解ける RMQ を <f(n), g(n)> で解くアルゴリズムが存在
 → LCA は <O(f(n))+O(n), O(g(n))+O(1)> で解ける 定理1 定理2
  • 5.
    ERATO若手輪読会 2014/11/19 RMQ toLCA 5 LCA を <f(n), g(n)> で解くアルゴリズムが存在
 → RMQは <f(n)+O(n), g(n)+O(1)> で解ける 定理1 • 列Aを Cartesian Tree に変換 • Cartesian Tree • 値の2分ヒープ構造 • 頂点ラベルはインデックス • 子の左右が列の左右と一致 id 1 2 3 4 5 6 A[id] 1 8 2 6 3 5 1 3 2 5 4 6
  • 6.
    ERATO若手輪読会 2014/11/19 RMQ toLCA 6 • RMQ(l,r):
 Cartesian Tree上でLCA(l,r)を解く ことで最小値インデックスが求まる
 • Cartesian Treeの構築: O(n) • 最小値そのものが知りたいとき:
 メモリアクセス O(1) id 1 2 3 4 5 6 A[id] 1 8 2 6 3 5 1 3 2 5 4 6 LCA を <f(n), g(n)> で解くアルゴリズムが存在
 → RMQは <f(n)+O(n), g(n)+O(1)> で解ける 定理1
  • 7.
    ERATO若手輪読会 2014/11/19 LCA toRMQ • 木 T を Euler Tour で展開 • Euler Tour: • TをDFSで辿る • 頂点の訪問順で列を定義 • 列の長さは必ず2n-1 7 RMQ を <f(n), g(n)> で解くアルゴリズムが存在
 → LCA は <O(f(n))+O(n), O(g(n))+O(1)> で解ける 定理2 4 65 2 1 3 T id 1 2 3 4 5 6 7 8 9 10 11 A[id] 1 2 1 3 4 3 5 3 6 3 1
  • 8.
    ERATO若手輪読会 2014/11/19 LCA toRMQ • LCA(u,v):
 深さ配列d上でRMQ(l,r)
 (l, rはu, vのAでの出現位置) • Euler Tourへの展開: O(n) • LCAの頂点番号取得: 
 メモリアクセス O(1) 8 RMQ を <f(n), g(n)> で解くアルゴリズムが存在
 → LCA は <O(f(n))+O(n), O(g(n))+O(1)> で解ける 定理2 4 65 2 1 3 T id 1 2 3 4 5 6 7 8 9 10 11 A[id] 1 2 1 3 4 3 5 3 6 3 1 d[id] 0 1 0 1 2 1 2 1 2 1 0
  • 9.
    ERATO若手輪読会 2014/11/19 LCAとRMQ • 定理より、LCAまたは RMQ のどちらか一方が <O(n), O(1)> で解ければ、もう一方も<O(n), O(1)> • LCAとRMQには、それぞれ様々なアルゴリズムが 提案されている 9
  • 10.
    ERATO若手輪読会 2014/11/19 RMQのアルゴリズム 10 空間 前処理クエリ Segment Tree (動的) O(n) O(n) O(log n) Sparse Table O(n logn) O(n logn) O(1) Cartesian Tree + LCA O(n) + ? O(n) + ? O(1) + ? ※ここでは各値を表すのに必要な O(logn) は無視
  • 11.
    ERATO若手輪読会 2014/11/19 LCAのアルゴリズム 11 空間 前処理クエリ Doubling O(n logn) O(n logn) O(log n) Heavy Path Decomposition O(n) O(n) O(1) Euler Tour + RMQ O(n) + ? O(n) + ? O(1) + ? ※ここでは各値を表すのに必要な O(logn) は無視
  • 12.
    ERATO若手輪読会 2014/11/19 <O(n), O(1)>アルゴリズム •LCAはHeavy Path Decompositionを利用して、 直接 <O(n), O(1)> で解くことが可能 • ただし、簡潔化が難しい • LCAで必要とされるRMQがある特殊な条件を満た すことを利用して、RMQを <O(n), O(1)> で解く 12
  • 13.
    ERATO若手輪読会 2014/11/19 1RMQ • LCA:Euler Tour の深さ配列でRMQ • 1回の移動で深さはちょうど1だけ変わる • 深さ配列の隣接要素同士は+1 か -1 だけ異なる • 隣接要素の変化が 1 である列上での RMQ を 1RMQ と呼ぶ • 1RMQ が <O(n), O(1)> で解ければ、LCA も <O(n), O(1)> で解ける 134 65 2 1 3 id 1 2 3 4 5 6 7 8 9 10 11 A[id] 1 2 1 3 4 3 5 3 6 3 1 d[id] 0 1 0 1 2 1 2 1 2 1 0 +1 +1 +1 +1 +1 -1 -1-1-1-1
  • 14.
    ERATO若手輪読会 2014/11/19 <O(n), O(1)>RMQ RMQを <O(n), O(1)> で解く流れ 1. RMQ を Cartesian Tree に変換し、LCA に帰着
 ( 時間・空間: O(n) ) 2. LCA を Euler Tour で展開し、 1RMQ に帰着
 ( 時間・空間: O(n) ) 3. 1RMQ を以下のテクニックで <O(n), O(1)> で解く • ブロック分割 • Sparse Table • Table Lookup 14 [Bender et. al. '05]
  • 15.
    ERATO若手輪読会 2014/11/19 ブロック分割 • 簡潔データ構造の典型テクニック •長さnの列を長さs = logn/2のブロックに分割 • ブロックの数 B = 2n/logn • 各ブロックの最小値インデックスを O(n) で前計算 • 全体の RMQ クエリは、以下のクエリに分割される • ブロックの区間に対する RMQ クエリ1回 • ブロック内部に対する RMQ クエリ2回 15 id 1 2 3 4 5 6 7 8 9 101112131415161718192021222324252627282930 A[id] 1 2 1 3 4 3 5 3 6 3 1 8 4 9 11 4 1 5 6 3 2 5 2 5 2 1 9 8 4 1
  • 16.
    ERATO若手輪読会 2014/11/19 ブロック分割 • 簡潔データ構造の典型テクニック •長さnの列を長さs = logn/2のブロックに分割 • ブロックの数 B = 2n/logn • 各ブロックの最小値インデックスを O(n) で前計算 • 全体の RMQ クエリは、以下のクエリに分割される • ブロックの区間に対する RMQ = Sparse Table • ブロック内部に対する RMQ = Table Lookup 16 id 1 2 3 4 5 6 7 8 9 101112131415161718192021222324252627282930 A[id] 1 2 1 3 4 3 5 3 6 3 1 8 4 9 11 4 1 5 6 3 2 5 2 5 2 1 9 8 4 1 それぞれ <O(n), O(1)> で 解ければOK
  • 17.
    ERATO若手輪読会 2014/11/19 Sparse Table •i 番目から長さ2kの区間の最小値インデックスをそれ ぞれ記憶したO(n logn)のテーブルを持つ • 構築: O(n logn) • S[i][k+1] = argmin( A[S[i][k]], A[S[i+2k][k]] ) • クエリ: O(1) • RMQ(i, j) = argmin( A[S[i][k]], A[S[j-2k+1][k]] ) • k = floor( log(j-i) ) ← O(1)で求められると仮定 17 id 1 2 3 4 5 6 7 8 A[id] 1 2 1 3 4 3 5 3 id 1 2 3 4 5 6 7 8 A[id] 1 2 1 3 4 3 5 3 構築: クエリ:
  • 18.
    ERATO若手輪読会 2014/11/19 Sparse Table •i 番目から長さ2kの区間の最小値インデックスをそれ ぞれ記憶したO(n logn)のテーブルを持つ • B個のブロックに対し、<O(B logB), O(1)> のアルゴ リズム • B = 2n/lognより、
 B logB = 2n/logn・(log2n - loglogn) = O(n) 18 id 1 2 3 4 5 6 7 8 A[id] 1 2 1 3 4 3 5 3 id 1 2 3 4 5 6 7 8 A[id] 1 2 1 3 4 3 5 3 構築: クエリ:
  • 19.
    ERATO若手輪読会 2014/11/19 Table Lookup •簡潔データ構造の典型テクニック その2 • 1 で変化している列の最小値インデックスは、値 そのものを見なくても変化量だけ見ればわかる • すべての変化パターンと区間 [l,r]について、最小値 インデックスを記録して参照すればよい • 長さ s の列の変化のパターンは2s通り • よって、<O(s22s), O(1)> のアルゴリズム • s = logn/2より、s22s = O(log2n n) = o(n) 19
  • 20.
    ERATO若手輪読会 2014/11/19 <O(n), O(1)>RMQ RMQ を <O(n), O(1)> で解けた!!! 1. RMQ を Cartesian Tree に変換し、LCA に帰着
 ( 時間・空間: O(n) ) 2. LCA を Euler Tour で展開し、 1RMQ に帰着
 ( 時間・空間: O(n) ) 3. 1RMQ を以下のテクニックで <O(n), O(1)> で解く • ブロック分割 • Sparse Table • Table Lookup 20 [Bender et. al. '05]
  • 21.
  • 22.
    ERATO若手輪読会 2014/11/19 簡潔RMQ RMQ を<O(n), O(1)> で解けた!!! 1. RMQ を Cartesian Tree に変換し、LCA に帰着
 ( 時間・空間: O(n) ) 2. LCA を Euler Tour で展開し、 1RMQ に帰着
 ( 時間・空間: O(n) ) 3. 1RMQ を以下のテクニックで <O(n), O(1)> で解く • ブロック分割 • Sparse Table • Table Lookup 22 BP (Balanced Parentheses) 表現で2n bitに BP上の rank( - rank) が深さに対応 → Euler Tour なしに 1RMQ 分割を多段にすることで o(n) bitに [Sadakane '07]
  • 23.
    ERATO若手輪読会 2014/11/19 簡潔RMQ • 問題点:BP 上でわかるのは pre-order
 RMQ で求めたいインデックスは
 Cartesian tree 上では in-order • 対応を覚える場合O(n logn) bit を使う → not 簡潔 • Cartesian Tree に dummy node を n 個付加するこ とで解決 → 4n + o(n) bitに 23 [Sadakane '07] id 1 2 3 4 5 6 A[id] 1 8 2 6 3 5 1 3 2 5 4 6 ( ( ( ) ( ( ) ( ) ) ) 1 1 3 2 2 8 4 6 5 3 6 5
  • 24.
    ERATO若手輪読会 2014/11/19 簡潔RMQ • 問題点:BP 上でわかるのは pre-order
 RMQ で求めたいインデックスは
 Cartesian tree 上では in-order • 対応を覚える場合O(n logn) bit を使う → not 簡潔 • Cartesian Tree に dummy node を n 個付加するこ とで解決 → 4n + o(n) bitに 24 [Sadakane '07] id 1 2 3 4 5 6 A[id] 1 8 2 6 3 5 1 3 2 5 4 6 ( ( ( ) ( ( ) ( ) ) ) 1 1 3 2 2 8 4 6 5 3 6 5 2n にしたい
  • 25.
    ERATO若手輪読会 2014/11/19 簡潔RMQ • CartesianTree + BP の代わりに 2D-Min Heap + DFUDS (Depth-First Unary Degree Sequence) • 流れ: • 入力列を 2D-Min Heap を表すDFUDSに変換 • O(n)時間、 DFUDSは 2n bit • DFUDS に必要な索引を付加 • O(n)時間、索引は o(n) bit • 索引付き DFUDS 上で LCAを解く • 内部で rank, select, findopen, 1RMQ 等を使用 • O(1) 時間 25 [Fischer '09] id 0 1 2 3 4 5 6 A[id] - 1 8 2 6 3 5 1 32 54 6 2D-Min Heap 0 DFUDS: ( ( ) ( ( ) ) ( ( ) ) ( ) )
  • 26.
    ERATO若手輪読会 2014/11/19 簡潔RMQ • CartesianTree + BP の代わりに 2D-Min Heap + DFUDS (Depth-First Unary Degree Sequence) • 2D-Min Heap: • 自分より左かつ小さいもののうち、最も右にある ものを親にする 26 [Fischer '09] id 0 1 2 3 4 5 6 A[id ] - 1 8 2 6 3 5 1 3 2 5 4 6 1 32 54 6 Cartesian Tree 2D-Min Heap 0
  • 27.
    ERATO若手輪読会 2014/11/19 簡潔RMQ • RMQ(i,j)は、2D-Min Heap 上では、 • LCA(i, j)が i → RMQ(i, j) = i • それ以外 → RMQ(i, j) = LCA(i, j)の子で、jの先祖 27 [Fischer '09] id 0 1 2 3 4 5 6 A[id ] - 1 8 2 6 3 5 2D-Min Heap 1 32 54 6 0 i j LCA(2,4) RMQ(2,4)
  • 28.
    ERATO若手輪読会 2014/11/19 簡潔RMQ • CartesianTree + BP の代わりに 2D-Min Heap + DFUDS (Depth-First Unary Degree Sequence) • DFUDS: • 葉は ( ) • w 個の子 T1, ..., Tw の親は w+1 個の ( と 1個の ) の後、 子を続ける.ただし、子の表現は先頭の ( を1つ削る 28 [Fischer '09] ( ( ) ( ( ) ) ( ( ) ) ( ) ) id 0 1 2 3 4 5 6 d 1 2 1 2 3 2 3 4 3 4 3 2 1 0 A[id] - 1 8 2 6 3 5 1 32 54 6 0
  • 29.
    ERATO若手輪読会 2014/11/19 • RMQ(i,j) 1. l ← select)(U, i+1), r ← select)(U, j) 2. w = 1RMQ(l, r) 3. if rank)(U, findopen(U, w)) = i, then return i 4. else rank)(U, w) 29 簡潔RMQ [Fischer '09] U: ( ( ) ( ( ) ) ( ( ) ) ( ) ) id 0 1 2 3 4 5 6 d 1 2 1 2 3 2 1 2 3 2 1 2 1 0 A[id] - 1 8 2 6 3 5 1 32 54 6 0 i j l r 1RMQ(l,r) findopen
  • 30.
    ERATO若手輪読会 2014/11/19 • RMQ(i,j) 1. l ← select)(U, i+1), r ← select)(U, j) 2. w = 1RMQ(l, r) 3. if rank)(U, findopen(U, w)) = i, then return i 4. else rank)(U, w) 30 簡潔RMQ [Fischer '09] U: ( ( ) ( ( ) ) ( ( ) ) ( ) ) id 0 1 2 3 4 5 6 d 1 2 1 2 3 2 1 2 3 2 1 2 1 0 A[id] - 1 8 2 6 3 5 1 32 54 6 0 i j l r 1RMQ(l,r) findopen DFUDS 上の RMQ では、 w は i と j のLCAの子であり、 jの祖先である (ただし LCA が iのとき w=i ) [Jansson et. al. '07]
  • 31.
    ERATO若手輪読会 2014/11/19 • RMQ(i,j) 1. l ← select)(U, i+1), r ← select)(U, j) 2. w = 1RMQ(l, r) 3. if rank)(U, findopen(U, w)) = i, then return i 4. else rank)(U, w) 31 簡潔RMQ [Fischer '09] U: ( ( ) ( ( ) ) ( ( ) ) ( ) ) id 0 1 2 3 4 5 6 d 1 2 1 2 3 2 1 2 3 2 1 2 1 0 A[id] - 1 8 2 6 3 5 1 32 54 6 0 i j l r 1RMQ(l,r) findopen 親が preorder わかる
  • 32.
    ERATO若手輪読会 2014/11/19 • RMQ(i,j) 1. l ← select)(U, i+1), r ← select)(U, j) 2. w = 1RMQ(l, r) 3. if rank)(U, findopen(U, w)) = i, then return i 4. else rank)(U, w) 32 簡潔RMQ [Fischer '09] U: ( ( ) ( ( ) ) ( ( ) ) ( ) ) id 0 1 2 3 4 5 6 d 1 2 1 2 3 2 1 2 3 2 1 2 1 0 A[id] - 1 8 2 6 3 5 1 32 54 6 0 i j l r 1RMQ(l,r) findopen自分の preorder わかる
  • 33.
    ERATO若手輪読会 2014/11/19 割愛したところ • 入力列から直接2n bit のDFUDSへ O(n) で変換 • 簡潔でない方法: スタックを利用したアルゴリズム • 簡潔な方法: スタックを簡潔にする • 1RMQ をより簡潔に • o(n) で隠された部分がより succinct に • 具体的には、(loglogn)2 かかっていたところが loglogn に落とせる 33
  • 34.
    ERATO若手輪読会 2014/11/19 まとめ • LCAと RMQは適切に変換することで等価な問題 として解ける • LCA to RMQ: Euler Tour, BP, DFUDS • RMQ to LCA: Cartesian Tree, 2D-Min Heap • LCA で要求される RMQ が 1RMQ であることを 利用し、<O(n), O(1)> を実現する • 木の簡潔表現と LCA, RMQ の簡潔辞書により、 2n + o(n) bitで、<O(n), O(1)> を実現する 34