Submit Search
Upload
図と実装で理解する『木構造入門』
•
0 likes
•
2,063 views
P
Proktmr
Follow
JOI春合宿でも頻出の木構造について扱います。部分木に対する一括操作やLCAの求め方などについて学ぶことができます。図と実装が掲載されているので、理解をより深めることができます。
Read less
Read more
Engineering
Report
Share
Report
Share
1 of 59
Download now
Download to read offline
Recommended
指数時間アルゴリズム入門
指数時間アルゴリズム入門
Yoichi Iwata
プログラミングコンテストでのデータ構造
プログラミングコンテストでのデータ構造
Takuya Akiba
プログラミングコンテストでのデータ構造 2 ~動的木編~
プログラミングコンテストでのデータ構造 2 ~動的木編~
Takuya Akiba
最小カットを使って「燃やす埋める問題」を解く
最小カットを使って「燃やす埋める問題」を解く
shindannin
プログラミングコンテストでのデータ構造 2 ~平衡二分探索木編~
プログラミングコンテストでのデータ構造 2 ~平衡二分探索木編~
Takuya Akiba
Re永続データ構造が分からない人のためのスライド
Re永続データ構造が分からない人のためのスライド
Masaki Hara
最大流 (max flow)
最大流 (max flow)
HCPC: 北海道大学競技プログラミングサークル
明日使えないすごいビット演算
明日使えないすごいビット演算
京大 マイコンクラブ
Recommended
指数時間アルゴリズム入門
指数時間アルゴリズム入門
Yoichi Iwata
プログラミングコンテストでのデータ構造
プログラミングコンテストでのデータ構造
Takuya Akiba
プログラミングコンテストでのデータ構造 2 ~動的木編~
プログラミングコンテストでのデータ構造 2 ~動的木編~
Takuya Akiba
最小カットを使って「燃やす埋める問題」を解く
最小カットを使って「燃やす埋める問題」を解く
shindannin
プログラミングコンテストでのデータ構造 2 ~平衡二分探索木編~
プログラミングコンテストでのデータ構造 2 ~平衡二分探索木編~
Takuya Akiba
Re永続データ構造が分からない人のためのスライド
Re永続データ構造が分からない人のためのスライド
Masaki Hara
最大流 (max flow)
最大流 (max flow)
HCPC: 北海道大学競技プログラミングサークル
明日使えないすごいビット演算
明日使えないすごいビット演算
京大 マイコンクラブ
プログラミングコンテストでの乱択アルゴリズム
プログラミングコンテストでの乱択アルゴリズム
Takuya Akiba
Rolling Hashを殺す話
Rolling Hashを殺す話
Nagisa Eto
勉強か?趣味か?人生か?―プログラミングコンテストとは
勉強か?趣味か?人生か?―プログラミングコンテストとは
Takuya Akiba
Convex Hull Trick
Convex Hull Trick
HCPC: 北海道大学競技プログラミングサークル
ユークリッド最小全域木
ユークリッド最小全域木
理玖 川崎
Rolling hash
Rolling hash
HCPC: 北海道大学競技プログラミングサークル
Binary indexed tree
Binary indexed tree
HCPC: 北海道大学競技プログラミングサークル
色々なダイクストラ高速化
色々なダイクストラ高速化
yosupo
双対性
双対性
Yoichi Iwata
プログラミングコンテストでの動的計画法
プログラミングコンテストでの動的計画法
Takuya Akiba
RMQ クエリ処理
RMQ クエリ処理
HCPC: 北海道大学競技プログラミングサークル
二部グラフの最小点被覆と最大安定集合と最小辺被覆の求め方
二部グラフの最小点被覆と最大安定集合と最小辺被覆の求め方
Kensuke Otsuki
直交領域探索
直交領域探索
okuraofvegetable
動的計画法を極める!
動的計画法を極める!
HCPC: 北海道大学競技プログラミングサークル
2SAT(充足可能性問題)の解き方
2SAT(充足可能性問題)の解き方
Tsuneo Yoshioka
Topological sort
Topological sort
HCPC: 北海道大学競技プログラミングサークル
ウェーブレット木の世界
ウェーブレット木の世界
Preferred Networks
様々な全域木問題
様々な全域木問題
tmaehara
AtCoder Beginner Contest 035 解説
AtCoder Beginner Contest 035 解説
AtCoder Inc.
Union find(素集合データ構造)
Union find(素集合データ構造)
AtCoder Inc.
競プロは人生の役に立つ!
競プロは人生の役に立つ!
Kensuke Otsuki
区間分割の仕方を最適化する動的計画法 (JOI 2021 夏季セミナー)
区間分割の仕方を最適化する動的計画法 (JOI 2021 夏季セミナー)
Kensuke Otsuki
More Related Content
What's hot
プログラミングコンテストでの乱択アルゴリズム
プログラミングコンテストでの乱択アルゴリズム
Takuya Akiba
Rolling Hashを殺す話
Rolling Hashを殺す話
Nagisa Eto
勉強か?趣味か?人生か?―プログラミングコンテストとは
勉強か?趣味か?人生か?―プログラミングコンテストとは
Takuya Akiba
Convex Hull Trick
Convex Hull Trick
HCPC: 北海道大学競技プログラミングサークル
ユークリッド最小全域木
ユークリッド最小全域木
理玖 川崎
Rolling hash
Rolling hash
HCPC: 北海道大学競技プログラミングサークル
Binary indexed tree
Binary indexed tree
HCPC: 北海道大学競技プログラミングサークル
色々なダイクストラ高速化
色々なダイクストラ高速化
yosupo
双対性
双対性
Yoichi Iwata
プログラミングコンテストでの動的計画法
プログラミングコンテストでの動的計画法
Takuya Akiba
RMQ クエリ処理
RMQ クエリ処理
HCPC: 北海道大学競技プログラミングサークル
二部グラフの最小点被覆と最大安定集合と最小辺被覆の求め方
二部グラフの最小点被覆と最大安定集合と最小辺被覆の求め方
Kensuke Otsuki
直交領域探索
直交領域探索
okuraofvegetable
動的計画法を極める!
動的計画法を極める!
HCPC: 北海道大学競技プログラミングサークル
2SAT(充足可能性問題)の解き方
2SAT(充足可能性問題)の解き方
Tsuneo Yoshioka
Topological sort
Topological sort
HCPC: 北海道大学競技プログラミングサークル
ウェーブレット木の世界
ウェーブレット木の世界
Preferred Networks
様々な全域木問題
様々な全域木問題
tmaehara
AtCoder Beginner Contest 035 解説
AtCoder Beginner Contest 035 解説
AtCoder Inc.
Union find(素集合データ構造)
Union find(素集合データ構造)
AtCoder Inc.
What's hot
(20)
プログラミングコンテストでの乱択アルゴリズム
プログラミングコンテストでの乱択アルゴリズム
Rolling Hashを殺す話
Rolling Hashを殺す話
勉強か?趣味か?人生か?―プログラミングコンテストとは
勉強か?趣味か?人生か?―プログラミングコンテストとは
Convex Hull Trick
Convex Hull Trick
ユークリッド最小全域木
ユークリッド最小全域木
Rolling hash
Rolling hash
Binary indexed tree
Binary indexed tree
色々なダイクストラ高速化
色々なダイクストラ高速化
双対性
双対性
プログラミングコンテストでの動的計画法
プログラミングコンテストでの動的計画法
RMQ クエリ処理
RMQ クエリ処理
二部グラフの最小点被覆と最大安定集合と最小辺被覆の求め方
二部グラフの最小点被覆と最大安定集合と最小辺被覆の求め方
直交領域探索
直交領域探索
動的計画法を極める!
動的計画法を極める!
2SAT(充足可能性問題)の解き方
2SAT(充足可能性問題)の解き方
Topological sort
Topological sort
ウェーブレット木の世界
ウェーブレット木の世界
様々な全域木問題
様々な全域木問題
AtCoder Beginner Contest 035 解説
AtCoder Beginner Contest 035 解説
Union find(素集合データ構造)
Union find(素集合データ構造)
Similar to 図と実装で理解する『木構造入門』
競プロは人生の役に立つ!
競プロは人生の役に立つ!
Kensuke Otsuki
区間分割の仕方を最適化する動的計画法 (JOI 2021 夏季セミナー)
区間分割の仕方を最適化する動的計画法 (JOI 2021 夏季セミナー)
Kensuke Otsuki
Aizu-2017: B
Aizu-2017: B
HCPC: 北海道大学競技プログラミングサークル
Operations research yonezawa_no1
Operations research yonezawa_no1
ssuser0bebd2
T82 aoitan あおいたんのパズルを数学しましょうか_修正版
T82 aoitan あおいたんのパズルを数学しましょうか_修正版
Masami Yabushita
わんくま勉強会東京#82 あおいたんのパズルを数学しましょうか
わんくま勉強会東京#82 あおいたんのパズルを数学しましょうか
Masami Yabushita
Rubysapporo Stringsearch
Rubysapporo Stringsearch
Akio Ishida
AtCoder Beginner Contest 006 解説
AtCoder Beginner Contest 006 解説
AtCoder Inc.
210122 msi dp
210122 msi dp
Kensuke Otsuki
Similar to 図と実装で理解する『木構造入門』
(9)
競プロは人生の役に立つ!
競プロは人生の役に立つ!
区間分割の仕方を最適化する動的計画法 (JOI 2021 夏季セミナー)
区間分割の仕方を最適化する動的計画法 (JOI 2021 夏季セミナー)
Aizu-2017: B
Aizu-2017: B
Operations research yonezawa_no1
Operations research yonezawa_no1
T82 aoitan あおいたんのパズルを数学しましょうか_修正版
T82 aoitan あおいたんのパズルを数学しましょうか_修正版
わんくま勉強会東京#82 あおいたんのパズルを数学しましょうか
わんくま勉強会東京#82 あおいたんのパズルを数学しましょうか
Rubysapporo Stringsearch
Rubysapporo Stringsearch
AtCoder Beginner Contest 006 解説
AtCoder Beginner Contest 006 解説
210122 msi dp
210122 msi dp
図と実装で理解する『木構造入門』
1.
図と実装で理解する 木構造入門 @Pro_ktmr JOI2019 優秀賞
2.
2 注意 • 内容の正確性には十分注意していますが、間 違った情報が含まれることもあります。何か お気づきのことがあればご連絡ください。 • このスライドのサンプルコードはC++で実装さ れています。
3.
JOI2019 春合宿 • JOI2019春合宿の問題の解法/概要を見てみる •
Segment Tree 木構造 貪欲法 Segment Tree Segment Tree ダイクストラ法 Segment Tree 木構造 動的計画法 Segment Tree 木構造 分割統治 3
4.
JOI2019 春合宿 • JOI2019春合宿の問題の解法/概要を見てみる •
Segment Tree 木構造 貪欲法 Segment Tree Segment Tree ダイクストラ法 Segment Tree 木構造 動的計画法 Segment Tree 木構造 分割統治 • 木構造に関する問題が3問も出題されている! 4
5.
JOI春合宿と木構造 • 2019年に限らず、例年2~3問ほど木構造に関 する問題が出題されています • グラフ理論に見せかけた木構造の問題もあります •
グラフ理論の問題の部分点解法で木を使うこともあります • Interactive / Communication / Output Onlyでも出題されています • 木構造に関する問題を解くには典型的な知識が 必要なことも多く、逆に知識があれば簡単なこ とも多いです • なので勉強しましょう 5
6.
木構造入門 1. 木構造とは i. 木構造 ii.
根つき木 iii. 根つき木の実装 2. DFS木 I. 深さ優先探索とDFS木 II. DFS木の作り方 III. DFS木と部分木 3. Euler Tour I. Euler TourとLCA 6
7.
木構造入門 1. 木構造とは i. 木構造 ii.
根つき木 iii. 根つき木の実装 2. DFS木 I. 深さ優先探索とDFS木 II. DFS木の作り方 III. DFS木と部分木 3. Euler Tour I. Euler TourとLCA 7
8.
木構造とは • 頂点(ノード)と辺(エッジ)か ら構成されている • ノードがN個の時、エッジは N-1本 •
連結(すべてのノード間で行 き来できる) • 2つのノード間の最短路が一 意に決まる • 閉路(サイクル)がない • グラフの特殊な場合で、うれ しい性質がたくさんあるイ メージ 8
9.
木構造とは • 頂点(ノード)と辺(エッジ)か ら構成されている • ノードがN個の時、エッジは N-1本 •
連結(すべてのノード間で行 き来できる) • 2つのノード間の最短路が一 意に決まる • 閉路(サイクル)がない • 誰がどう考えてもこのルート が明らかに最短 9 終 始
10.
根つき木 • 木のうれしい性質を最大限使 うために、根(ルート)つき木 を考えることが多い • 問題で根が指定されていない 場合は適当に決めてしまう 10
11.
根つき木 • 木のうれしい性質を最大限使 うために、根(ルート)つき木 を考えることが多い • 問題で根が指定されていない 場合は適当に決めてしまう 11 根
12.
根つき木 • 木のうれしい性質を最大限使 うために、根(ルート)つき木 を考えることが多い • 問題で根が指定されていない 場合は適当に決めてしまう 12 根
13.
根つき木 • 木のうれしい性質を最大限使 うために、根(ルート)つき木 を考えることが多い • 問題で根が指定されていない 場合は適当に決めてしまう 13 根
14.
根つき木 • 木のうれしい性質を最大限使 うために、根(ルート)つき木 を考えることが多い • 問題で根が指定されていない 場合は適当に決めてしまう 14 根
15.
家族関係 • 各ノードは0個以上の子ノー ドを持つ • 根以外のノードは1個の親 ノードを持つ •
同じ親を持つノードは兄弟 ノードと呼ばれる • 子ノードやその子ノードなど は子孫ノードと呼ばれる • 親ノードやその親ノードなど は先祖ノードと呼ばれる • 辺が1本しか出ていない(次数 が1の)ノードを葉と呼ぶ 15 子 自 親 兄 弟
16.
家族関係 • 各ノードは0個以上の子ノー ドを持つ • 根以外のノードは1個の親 ノードを持つ •
同じ親を持つノードは兄弟 ノードと呼ばれる • 子ノードやその子ノードなど は子孫ノードと呼ばれる • 親ノードやその親ノードなど は先祖ノードと呼ばれる • 辺が1本しか出ていない(次数 が1の)ノードを葉と呼ぶ 16
17.
3 根つき木の実装 • 配列parent[N]を用意して親 ノードの番号を入れる • 必要に応じてvector<int> children[N]を用意して子ノー ドの一覧も保持しておいても よい 17 2 5 4 1 0 6
18.
3 根つき木の実装 • 配列parent[N]を用意して親 ノードの番号を入れる • 必要に応じてvector<int> children[N]を用意して子ノー ドの一覧も保持しておいても よい •
parentって長いので、parと 略す人が多い(気がする) • 根の親は-1にしたり、自分自 身(par[4] = 4)にする 18 2 5 4 1 0 6 par[4] = -1 par[5] = 4 par[2] = 5 par[1] = 4 par[0] = 4 par[3] = 0 par[6] = 0
19.
3 根つき木の実装 • 配列parent[N]を用意して親 ノードの番号を入れる • 必要に応じてvector<int> children[N]を用意して子ノー ドの一覧も保持しておいても よい •
chiって略す人は見たことな い気が・・・ 19 2 5 4 1 0 6 chi[4] = {5,1,0} chi[5] = {2} chi[2] = {} chi[1] = {} chi[0] = {3,6} chi[3] = {} chi[6] = {}
20.
木構造入門 1. 木構造とは i. 木構造 ii.
根つき木 iii. 根つき木の実装 2. DFS木 I. 深さ優先探索とDFS木 II. DFS木の作り方 III. DFS木と部分木 3. Euler Tour I. Euler TourとLCA 20
21.
3 深さ優先探索(DFS) • 木上で深さ優先探索(DFS)を 行う • ノードに子があれば次はその 子ノードを探索する •
子がなくなるまで深く潜って いく 21 2 5 4 1 0 6
22.
3 DFS木 • DFSの探索順にノード番号を 振りなおすと、DFS木になる 22 2 5 4 1 0 6
23.
3 DFS木 • DFSの探索順にノード番号を 振りなおすと、DFS木になる 23 2 5 0 1 0 6
24.
3 DFS木 • DFSの探索順にノード番号を 振りなおすと、DFS木になる 24 2 1 0 1 0 6
25.
3 DFS木 • DFSの探索順にノード番号を 振りなおすと、DFS木になる 25 2 1 0 1 0 6
26.
3 DFS木 • DFSの探索順にノード番号を 振りなおすと、DFS木になる 26 2 1 0 3 0 6
27.
3 DFS木 • DFSの探索順にノード番号を 振りなおすと、DFS木になる 27 2 1 0 3 4 6
28.
5 DFS木 • DFSの探索順にノード番号を 振りなおすと、DFS木になる 28 2 1 0 3 4 6
29.
5 DFS木 • DFSの探索順にノード番号を 振りなおすと、DFS木になる 29 2 1 0 3 4 6
30.
5 DFS木 • DFSの探索順にノード番号を 振りなおすと、DFS木になる • 完成! 30 2 1 0 3 4 6
31.
DFS木を作る実装 • 再帰関数でDFSをする vector<int> children[N];
//もとの子 int par[N],pos[N]; //DFS木における親、DFS終了時のカウンターの状態 int c = 0; //cはカウンターでDFS木のノード番号になる void dfs(int v){ //vはもとのノード番号 int dfsOrder = c; c++; for(int i=0; i<children[v].size(); i++){ par[c] = dfsOrder; dfs(children[v][i]); } pos[dfsOrder] = c; } //変数が「もと」か「あと(DFS木)」かどちらを表しているのか混乱しないように注意 31
32.
5 DFS木の性質「部分木」 • あるノードvについて、その 子孫のDFSが終了したタイミ ングでのカウンターをpos[v] として保存しておく • vを根とする部分木は [v,pos[v])である •
[a,b)は半開区間でa≦i<bみ たいな 32 2 1 0 3 4 6 pos[0] = 7 pos[1] = 3 pos[5] = 6 pos[4] = 7 pos[3] = 4 pos[2] = 3 pos[6] = 7
33.
5 DFS木の性質「部分木」 • あるノードvについて、その 子孫のDFSが終了したタイミ ングでのカウンターをpos[v] として保存しておく • vを根とする部分木は [v,pos[v])である •
[a,b)は半開区間でa≦i<bみ たいな 33 2 1 0 3 4 6 pos[0] = 7 pos[1] = 3 pos[5] = 6 pos[4] = 7 pos[3] = 4 pos[2] = 3 pos[6] = 7 ノード4を根とする部分木は ノード[4,7) つまり4,5,6からなる
34.
5 部分木の使い方 • RAQやRUQを使って部分木に 対して一気に操作することが できる • 例)各辺にコストが設定され ている。以下のクエリを処理 する。 ①頂点vとその親との間の辺 のコストをxに変更する ②頂点vと根との最短距離dを 求める 34 2 1 0 3 4 6 v
0 1 2 3 4 5 6 d 0 5 6 2 4 4 5 5 1 2 4 0 1
35.
5 部分木の使い方 • RAQやRUQを使って部分木に 対して一気に操作することが できる • 例)各辺にコストが設定され ている。以下のクエリを処理 する。 ①頂点vとその親との間の辺 のコストをxに変更する ②頂点vと根との最短距離dを 求める •
クエリ:①v=4,x=2 35 2 1 0 3 4 6 v 0 1 2 3 4 5 6 d 0 5 6 2 2 2 3 5 1 2 2 0 1 コスト:4→2なので 部分木全部RAQ:-2
36.
5 部分木の使い方 • RAQやRUQを使って部分木に 対して一気に操作することが できる • 例)各辺にコストが設定され ている。以下のクエリを処理 する。 ①頂点vとその親との間の辺 のコストをxに変更する ②頂点vと根との最短距離dを 求める •
クエリ:②v=5 36 2 1 0 3 4 6 v 0 1 2 3 4 5 6 d 0 5 6 2 2 2 3 5 1 2 2 0 1
37.
補足:RAQとRUQとRMQ • RAQ:Range Add
Query 配列の特定の区間に対して値を加算する • RUQ:Range Update Query 配列の特定の区間に対して値を変更する • どちらも遅延評価Segment Treeや平方分割で 実装できます • RMQ:Range Minimum Query 配列の特定の区間の値の最小値を求める も後で出てきます 37
38.
木構造入門 1. 木構造とは i. 木構造 ii.
根つき木 iii. 根つき木の実装 2. DFS木 I. 深さ優先探索とDFS木 II. DFS木の作り方 III. DFS木と部分木 3. Euler Tour I. Euler TourとLCA 38
39.
5 Euler Tour • 頂点のDFSでの訪問順を vector等で持つことで、木を 直線にできる 39 2 1 0 3 4 6
40.
5 Euler Tour • 頂点のDFSでの訪問順を vector等で持つことで、木を 直線にできる •
0 → 1 → 2 → 1 → 0 → 3 → 0 → 4 → 5 → 4 → 6 → 4 → 0 40 2 1 0 3 4 6
41.
5 Euler Tour • 頂点のDFSでの訪問順を vector等で持つことで、木を 直線にできる •
0,1,2,1,0,3,0,4,5,4,6,4,0 • この配列の要素数は頂点数を Nとして2N-1個になる 41 2 1 0 3 4 6
42.
Euler Tourの実装 vector<int> EulerTour; int
pre[N]; void dfs(int v){ pre[v] = EulerTour.size(); EulerTour.push_back(v); for(int i=0; i<children[v].size(); i++){ dfs(edge[v][i]); EulerTour.push_back(v); } } • 関数名がdfsでさっきと被ってるが、その辺りは臨機応変に対 応する 42
43.
2 深さ • ところで、あるノードの根から の距離を深さと呼ぶ • 再帰関数で求められる int
depth(int v){ if(par[v] == -1) return 0; return depth(par[v])+1; } • 木の構造が変わらないならメモ 化するとよい int d[N] = {}; int depth(int v){ if(par[v] == -1) return 0; if(d[v] != 0) return d[v]; return d[v] = depth(par[v])+1; } 43 2 1 0 1 1 2
44.
LCA(最近共通祖先) • Lowest Common
Ancestor • 2つ以上のノードについて共 通な祖先のうちもっとも深い もの 44
45.
LCA(最近共通祖先) • Lowest Common
Ancestor • 2つ以上のノードについて共 通な祖先のうちもっとも深い もの 45 0 1 LCA(0,1)
46.
2 LCA(最近共通祖先) • Lowest Common
Ancestor • 2つ以上のノードについて共 通な祖先のうちもっとも深い もの 46 1 LCA(2,1)
47.
5 LCAとRMQ • さっきのスライドより右の木 のEuler Tourは 0,1,2,1,0,3,0,4,5,4,6,4,0 •
頂点vを最初に訪問した時の pushする前のvectorの要素 数をpre[v]とする 47 2 1 0 3 4 6
48.
5 LCAとRMQ • さっきのスライドより右の木 のEuler Tourは 0,1,2,1,0,3,0,4,5,4,6,4,0 •
頂点vを最初に訪問した時の pushする前のvectorの要素 数をpre[v]とする • 2つの頂点i, j (pre[i] < pre[j]) のLCAは RMQ[pre[i],pre[j])になる 48 2 1 0 3 4 6 pre[0] = 0 pre[1] = 1 pre[2] = 2 pre[3] = 5 pre[4] = 7 pre[5] = 8 pre[6] = 10
49.
LCAとRMQ • 0,1,2,1,0,3,0,4,5,4,6,4,0 49 pre[0] = 0 pre[1]
= 1 pre[2] = 2 pre[3] = 5 pre[4] = 7 pre[5] = 8 pre[6] = 10
50.
LCAとRMQ 50 pre[0] = 0 pre[1]
= 1 pre[2] = 2 pre[3] = 5 pre[4] = 7 pre[5] = 8 pre[6] = 10 Euler Tour 0 1 2 3 4 5 6 7 8 9 10 11 12 v 0 1 2 1 0 3 0 4 5 4 6 4 0
51.
LCAとRMQ 51 Euler Tour 0
1 2 3 4 5 6 7 8 9 10 11 12 v 0 1 2 1 0 3 0 4 5 4 6 4 0 v 0 1 2 3 4 5 6 pre[v] 0 1 2 5 7 8 10
52.
LCAとRMQ • 頂点2と5のLCAは? 52 Euler Tour
0 1 2 3 4 5 6 7 8 9 10 11 12 v 0 1 2 1 0 3 0 4 5 4 6 4 0 v 0 1 2 3 4 5 6 pre[v] 0 1 2 5 7 8 10
53.
LCAとRMQ • 頂点2と5のLCAは? Euler TourにおけるRMQ[pre[2]=2,pre[5]=8) →0 •
数スライド戻ると確かにLCA(2,5)=0 53 Euler Tour 0 1 2 3 4 5 6 7 8 9 10 11 12 v 0 1 2 1 0 3 0 4 5 4 6 4 0 v 0 1 2 3 4 5 6 pre[v] 0 1 2 5 7 8 10
54.
LCAとRMQ • 木構造を完全に忘れてただのRMQとしてLCAを 求めることができる • 他にはDoublingやHL分解などでもLCAを求め られる •
RMQを使うにはSegment Tree(or平方分割)を 実装する必要があるが、個人的にはEuler Tour→RMQが好き 54
55.
まとめ 「木があるということは数列があるということ」 55
56.
まとめ • 木構造の問題に対しては、適当な頂点を根とし てDFS木を作ると良いことが多い • 木があるということは数列があるということ vを根とした部分木は[v,pos[v]) •
LCA(i,j)はEuler Tourにおける RMQ[pre[i],pre[j])で求められる • 他にも辺や頂点をなくす(くっつける)場合の UnionFindによる縮約もJOI春合宿では頻出 56
57.
練習問題 • AOJ GRL_5_C
LCA https://onlinejudge.u- aizu.ac.jp/courses/library/5/GRL/5/GRL_5_C • AOJ GRL_5_D Range Query on a Tree https://onlinejudge.u- aizu.ac.jp/courses/library/5/GRL/5/GRL_5_D • 最初はAOJで基礎を固めるのがおすすめです 57
58.
練習問題 • JOI春合宿2015 Day2-3
Road Development https://atcoder.jp/contests/joisc2015/tasks/j oisc2015_g • このスライドの内容をすべて網羅しているよう な問題で、難しく重実装ですが、これさえ解け ればかなり力が付きます 58
Download now