Diese Präsentation wurde erfolgreich gemeldet.
Wir verwenden Ihre LinkedIn Profilangaben und Informationen zu Ihren Aktivitäten, um Anzeigen zu personalisieren und Ihnen relevantere Inhalte anzuzeigen. Sie können Ihre Anzeigeneinstellungen jederzeit ändern.

Spaceships 解説

4.042 Aufrufe

Veröffentlicht am

2013年の情報オリンピック春期トレーニング合宿(日本代表選抜合宿)の4日目に出題されたSpaceshipsの解説です。問題文等は http://www.ioi-jp.org/camp/2013/2013-sp-tasks/index.html で入手できます。

Veröffentlicht in: Technologie
  • Login to see the comments

Spaceships 解説

  1. 1. 1 / 277 Masaki Hara (qnighy)2013年 情報オリンピック春期トレーニング合宿にて
  2. 2. 2 / 277 有向木がたくさんあります 以下のクエリに高速で答えてください1. Aの親をBにする ◦ Aは木の根で、BはAの子孫ではない2. Aを親から切り離して木の根にする3. A,Bが同じ木に属するか判定し、 同じ木に属する場合はLCAを求める
  3. 3. 3 / 277 K 有向木がたくさんあります D B E I F A H C J L G
  4. 4. 4 / 277 K 有向木がたくさんあります 以下のクエリに高速で答えてください D B E I F A H C J L G
  5. 5. 5 / 277 K 1. Fの親をBにする D B E I F A H C J L G
  6. 6. 6 / 277 K 1. Fの親をBにする D B E I F A H C J L G
  7. 7. 7 / 277 K 1. Eの親をDにする D B E I F A H C J L G
  8. 8. 8 / 277 K 1. Eの親をDにする D B E I F A H C J L G
  9. 9. 9 / 277 K 2. Iを親から切り離して根にする D B E I F A H C J L G
  10. 10. 10 / 277 K 2. Iを親から切り離して根にする D B E I F A H C J L G
  11. 11. 11 / 277 K 2. Lを親から切り離して根にする D B E I F A H C J L G
  12. 12. 12 / 277 K 2. Lを親から切り離して根にする D B E I F A H C J L G
  13. 13. 13 / 277 K 3. GとHのLCAを求める D B E I F A H C J L G
  14. 14. 14 / 277 K 3. GとHのLCAを求める ◦ LCA: 最小共通先祖 D B E I F A H C J L G
  15. 15. 15 / 277 頂点数 𝑁 ≤ 5000 クエリ数 𝑄 ≤ 5000
  16. 16. 16 / 277 各頂点は親リンクを覚えておく クエリ1,2に対しては普通に答える B F
  17. 17. 17 / 277 K 各頂点は親リンクを覚えておく クエリ3に対しては D B E I F A H C J L G
  18. 18. 18 / 277 K 各頂点は親リンクを覚えておく クエリ3に対しては D ◦ Gから根に向かって辿る B E I F A H C J L G
  19. 19. 19 / 277 K 各頂点は親リンクを覚えておく クエリ3に対しては D ◦ Gから根に向かって辿る ◦ Hから根に向かって辿る B E I F A H C J L G
  20. 20. 20 / 277 K 各頂点は親リンクを覚えておく クエリ3に対しては D ◦ Gから根に向かって辿る ◦ Hから根に向かって辿る ◦ 並べる B E F H G
  21. 21. 21 / 277 各頂点は親リンクを覚えておく クエリ3に対しては ◦ Gから根に向かって辿る ◦ Hから根に向かって辿る ◦ 並べる K D B F G K D E H
  22. 22. 22 / 277 各頂点は親リンクを覚えておく クエリ3に対しては ◦ Gから根に向かって辿る ◦ Hから根に向かって辿る ◦ 根からの順番で並べる ◦ 一致する中で最も後ろのものを選ぶ K D B F G K D E H
  23. 23. 23 / 277 各頂点は親リンクを覚えておく クエリ3に対しては ◦ Gから根に向かって辿る ◦ Hから根に向かって辿る ◦ 根からの順番で並べる ◦ 根が一致しないときは-1
  24. 24. 24 / 277 頂点数 𝑁 ≤ 5000 クエリ数 𝑄 ≤ 5000 計算量は𝑂(𝑁𝑄)なので間に合う
  25. 25. 25 / 277 頂点数 𝑁 ≤ 106 クエリ数 𝑄 ≤ 106 辺の削除は行われない
  26. 26. 26 / 277 CがAとBのLCA C D F A B E
  27. 27. 27 / 277 CがAとBのLCA ↓辺を追加 C D F A B E
  28. 28. 28 / 277 CがAとBのLCA ↓辺を追加 C Cは依然としてAとBのLCA D F A B E
  29. 29. 29 / 277 CがAとBのLCA ↓辺を追加 Cは依然としてAとBのLCA 最終的にできる木の上でLCAを計算できればよい
  30. 30. 30 / 277 木の嬉しい順序(DFS順序) ◦ Preorder –頂点に入るときに記録する順序 A A, B, D, E, C, F B C D E F
  31. 31. 31 / 277 木の嬉しい順序(DFS順序) ◦ Postorder – 頂点から出るときに記録する順序 A D, E, B, F, C, A B C D E F
  32. 32. 32 / 277 木の嬉しい順序(DFS順序) ◦ Euler Tour  頂点から入るときに記録し、  頂点から出るときにも A 自分の親を記録する順序 B C D E F
  33. 33. 33 / 277 木の嬉しい順序(DFS順序) ◦ Euler Tour  頂点から入るときに記録し、  頂点から出るときにも A 自分の親を記録する順序 B C D E F A,
  34. 34. 34 / 277 木の嬉しい順序(DFS順序) ◦ Euler Tour  頂点から入るときに記録し、  頂点から出るときにも A 自分の親を記録する順序 B C D E F A, B,
  35. 35. 35 / 277 木の嬉しい順序(DFS順序) ◦ Euler Tour  頂点から入るときに記録し、  頂点から出るときにも A 自分の親を記録する順序 B C D E F A, B, D,
  36. 36. 36 / 277 木の嬉しい順序(DFS順序) ◦ Euler Tour  頂点から入るときに記録し、  頂点から出るときにも A 自分の親を記録する順序 B C D E F A, B, D, B,
  37. 37. 37 / 277 木の嬉しい順序(DFS順序) ◦ Euler Tour  頂点から入るときに記録し、  頂点から出るときにも A 自分の親を記録する順序 B C D E F A, B, D, B, E
  38. 38. 38 / 277 木の嬉しい順序(DFS順序) ◦ Euler Tour  頂点から入るときに記録し、  頂点から出るときにも A 自分の親を記録する順序 B C D E F A, B, D, B, E, B,
  39. 39. 39 / 277 木の嬉しい順序(DFS順序) ◦ Euler Tour  頂点から入るときに記録し、  頂点から出るときにも A 自分の親を記録する順序 B C D E F A, B, D, B, E, B, A,
  40. 40. 40 / 277 木の嬉しい順序(DFS順序) ◦ Euler Tour  頂点から入るときに記録し、  頂点から出るときにも A 自分の親を記録する順序 B C D E F A, B, D, B, E, B, A, C,
  41. 41. 41 / 277 木の嬉しい順序(DFS順序) ◦ Euler Tour  頂点から入るときに記録し、  頂点から出るときにも A 自分の親を記録する順序 B C D E F A, B, D, B, E, B, A, C, F,
  42. 42. 42 / 277 木の嬉しい順序(DFS順序) ◦ Euler Tour  頂点から入るときに記録し、  頂点から出るときにも A 自分の親を記録する順序 B C D E F A, B, D, B, E, B, A, C, F, C,
  43. 43. 43 / 277 木の嬉しい順序(DFS順序) ◦ Euler Tour  頂点から入るときに記録し、  頂点から出るときにも A 自分の親を記録する順序 B C D E F A, B, D, B, E, B, A, C, F, C, A
  44. 44. 44 / 277 木の嬉しい順序(DFS順序) ◦ Euler Tour  木の辺を、行きと帰りの2つの辺から なるとみなすときの A オイラー閉路に対応する B C D E F A, B, D, B, E, B, A, C, F, C, A
  45. 45. 45 / 277 木の嬉しい順序(DFS順序) ◦ Euler Tour  木の辺を、行きと帰りの2つの辺から なるとみなすときの オイラー閉路に対応する  オイラー閉路 (Euler Tour) : 全ての辺を1度ずつ通る閉路  オイラー路はケーニヒスベルクの橋問題で有名 Wikipediaより。 CC3.0-BY-SA
  46. 46. 46 / 277 Euler TourによるLCAの計算 A B C D E F
  47. 47. 47 / 277 Euler TourによるLCAの計算 A B D B E B A C F C A 1 2 3 2 3 2 1 2 3 2 1 A B C D E F
  48. 48. 48 / 277 Euler TourによるLCAの計算 A B D B E B A C F C A 1 2 3 2 3 2 1 2 3 2 1 A B C D E F
  49. 49. 49 / 277 Euler TourによるLCAの計算 A B D B E B A C F C A 1 2 3 2 3 2 1 2 3 2 1 A B C D E F
  50. 50. 50 / 277 Euler TourによるLCAの計算 A B D B E B A C F C A 1 2 3 2 3 2 1 2 3 2 1 A B C D E F
  51. 51. 51 / 277 Euler TourによるLCAの計算 A B D B E B A C F C A 1 2 3 2 3 2 1 2 3 2 1 A 深さ最小 B C D E F
  52. 52. 52 / 277 Euler TourによるLCAの計算 A B D B E B A C F C A 1 2 3 2 3 2 1 2 3 2 1 A RMQを利用 深さ最小 B C D E F
  53. 53. 53 / 277 正当性
  54. 54. 54 / 277 正当性: CがAとBのLCAのとき ◦ Euler Tour上でCは[A,B]に含まれる ◦ Euler Tour上で[A,B]に含まれるのはCの部分木 を言えばよい
  55. 55. 55 / 277 正当性(1): Euler Tour上でCは[A,B]に含まれる ◦ AからBに行くにはCを経由しないといけない(LCAの性質より) ◦ ので当たり前
  56. 56. 56 / 277 正当性(2): Euler Tour上で[A,B]に含まれるのは Cの部分木 ◦ Euler Tourにおいて部分木は連続した部分列として現れる ◦ ので当たり前
  57. 57. 57 / 277 LCAを求めて終わり?
  58. 58. 58 / 277 LCAを求めて終わり? ◦ あと少しだけやることがあります
  59. 59. 59 / 277 「削除がない場合の利点」の考察を思い出す
  60. 60. 60 / 277 「削除がない場合の利点」の考察を思い出す LCAが存在するなら、最終的な木の上で計算すれば よい
  61. 61. 61 / 277 「削除がない場合の利点」の考察を思い出す LCAが存在するなら、最終的な木の上で計算すれば よい
  62. 62. 62 / 277 A, Bが同じ木上にあるかどうかの判定が必要
  63. 63. 63 / 277 A, Bが同じ木上にあるかどうかの判定が必要 ですが
  64. 64. 64 / 277 A, Bが同じ木上にあるかどうかの判定が必要 ですが 辺の追加クエリしかないのでUnionFindでよい ということはすぐにわかると思います
  65. 65. 65 / 277 頂点数 𝑁 ≤ 106 クエリ数 𝑄 ≤ 106 辺の削除は行われない 𝑂(𝑁 + 𝑄 log 𝑁) なので間に合う
  66. 66. 66 / 277 ここまでの両方を実装すれば40点
  67. 67. 67 / 277 ここまでの両方を実装すれば40点 複数のアルゴリズムを条件によって使い分けるテクは さすがに使っていると思います
  68. 68. 68 / 277 頂点数 𝑁 ≤ 106 クエリ数 𝑄 ≤ 106
  69. 69. 69 / 277 頂点数 𝑁 ≤ 106 クエリ数 𝑄 ≤ 106 削除クエリもある
  70. 70. 70 / 277 追加も削除もある場合の頻出テク
  71. 71. 71 / 277 追加も削除もある場合の頻出テク ◦ クエリの(平方)分割 ◦ がんばって動的になんとかする
  72. 72. 72 / 277 追加も削除もある場合の頻出テク ◦ がんばって動的になんとかする
  73. 73. 73 / 277 追加も削除もある場合の頻出テク ◦ がんばって動的になんとかする
  74. 74. 74 / 277 木が静的な場合のLCA (復習)
  75. 75. 75 / 277 木が静的な場合のLCA (復習) ◦ Euler Tour上で必要とされるクエリは以下の通り
  76. 76. 76 / 277 木が静的な場合のLCA (復習) ◦ Euler Tour上で必要とされるクエリは以下の通り 1. 区間の最小値をとる
  77. 77. 77 / 277 木が静的な場合のLCA (復習) ◦ Euler Tour上で必要とされるクエリは以下の通り 1. 区間の最小値をとる ◦ RMQで実現可能
  78. 78. 78 / 277 木が動的な場合のLCA (絶望) ◦ Euler Tour上で必要とされるクエリは以下の通り 1. 区間の最小値をとる 2. ◦ RMQで実現可能な気がする
  79. 79. 79 / 277 木が動的な場合のLCA (絶望) ◦ Euler Tour上で必要とされるクエリは以下の通り 1. 区間の最小値をとる 2. 列の連結をする 3. ◦ RMQで実現可能な気がする
  80. 80. 80 / 277 木が動的な場合のLCA (絶望) ◦ Euler Tour上で必要とされるクエリは以下の通り 1. 区間の最小値をとる 2. 列の連結をする 3. 列の分割をする 4. ◦ RMQで実現可能な気がする
  81. 81. 81 / 277 木が動的な場合のLCA (絶望) ◦ Euler Tour上で必要とされるクエリは以下の通り 1. 区間の最小値をとる 2. 列の連結をする 3. 列の分割をする 4. それだけ?
  82. 82. 82 / 277 木が動的な場合のLCA (絶望) ◦ Euler Tour上で必要とされるクエリは以下の通り 1. 区間の最小値をとる 2. 列の連結をする 3. 列の分割をする 4. 区間に値を足す
  83. 83. 83 / 277 木が動的な場合のLCA (絶望) ◦ Euler Tour上で必要とされるクエリは以下の通り 1. 区間の最小値をとる 2. 列の連結をする 3. 列の分割をする 4. 区間に値を足す ◦ この業界では「Starry Sky木」として知られているもの
  84. 84. 84 / 277 木が動的な場合のLCA (絶望) ◦ Euler Tour上で必要とされるクエリは以下の通り 1. 区間の最小値をとる 2. 列の連結をする 3. 列の分割をする 4. 区間に値を足す ◦ この業界では「Starry Sky木」として知られているもの を平衡二分木として実装する必要がある (絶望)
  85. 85. 85 / 277 木が動的な場合のLCA (絶望) ◦ Euler Tour上で必要とされるクエリは以下の通り 1. 区間の最小値をとる 2. 列の連結をする 3. 列の分割をする 4. 区間に値を足す ◦ この業界では「Starry Sky木」として知られているもの を平衡二分木として実装する必要がある (絶望)  しかもmerge/splitベースで
  86. 86. 86 / 277 平衡二分木の中身は後回し
  87. 87. 87 / 277 平衡二分木の中身は後回し 平衡二分木を使った具体的な実装方法
  88. 88. 88 / 277 木の各頂点ごとに、Euler Tourのためのノードを2つ 用意する(𝑆 𝐴 , 𝐺 𝐴 ) ◦ 𝑆 𝐴 上には頂点Aの番号と、その深さが記録されている ◦ 𝐺 𝐴 上には頂点Aの親Pの番号と、その深さが記録されている ◦ Aが根のときは𝑆 𝐴 のみ使う A A 𝐺𝐵 𝑆𝐴 B B
  89. 89. 89 / 277 木の連結 A Depth 0 B C Depth 0 Depth 1 D E Depth 1 F Depth 1 𝑆𝐵 𝐵 , 𝑆𝐷 𝐷 , 𝐺 𝐷 𝐵 , 𝑆 𝐸 𝐸 , 𝐺 𝐸 (𝐵) Depth 2 𝑆 𝐴 𝐴 , 𝑆 𝐶 𝐶 , 𝑆 𝐹 𝐹 , 𝐺 𝐹 𝐶 , 𝐺 𝐹 (𝐴)
  90. 90. 90 / 277 木の連結 A 1. Euler TourをA点で分割 Depth 0 ◦ A直下ならどの位置でもいい  𝑆 𝐴 の直後がおすすめ B C Depth 0 Depth 1 D E Depth 1 F Depth 1 𝑆𝐵 𝐵 , 𝑆𝐷 𝐷 , 𝐺 𝐷 𝐵 , 𝑆 𝐸 𝐸 , 𝐺 𝐸 (𝐵) Depth 2 𝑆 𝐴 𝐴 ,                            𝑆 𝐶 𝐶 , 𝑆 𝐹 𝐹 , 𝐺 𝐹 𝐶 , 𝐺 𝐹 (𝐴)
  91. 91. 91 / 277 木の連結 A 1. Euler TourをA点で分割 Depth 0 2. Euler Tourを挿入 B C Depth 0 Depth 1 D E F Depth 1 Depth 1 Depth 2 𝑆 𝐴 𝐴 , 𝑆 𝐵 𝐵 , 𝑆 𝐷 𝐷 , 𝐺 𝐷 𝐵 , 𝑆 𝐸 𝐸 , 𝐺 𝐸 𝐵 , 𝐺 𝐵 (𝐸), 𝑆 𝐶 𝐶 , 𝑆 𝐹 𝐹 , 𝐺 𝐹 𝐶 , 𝐺 𝐹 (𝐴)
  92. 92. 92 / 277 木の連結 A 1. Euler TourをA点で分割 Depth 0 2. Euler Tourを挿入 3. 深さを調整 B C Depth 1 Depth 1 D E F Depth 2 Depth 2 Depth 2 𝑆 𝐴 𝐴 , 𝑆 𝐵 𝐵 , 𝑆 𝐷 𝐷 , 𝐺 𝐷 𝐵 , 𝑆 𝐸 𝐸 , 𝐺 𝐸 𝐵 , 𝐺 𝐵 (𝐸), 𝑆 𝐶 𝐶 , 𝑆 𝐹 𝐹 , 𝐺 𝐹 𝐶 , 𝐺 𝐹 (𝐴)
  93. 93. 93 / 277 木の削除: 追加のときと逆操作
  94. 94. 94 / 277 平衡Starry Sky Treeがあればよいことがわかった
  95. 95. 95 / 277 平衡Starry Sky Treeがあればよいことがわかった ではどのように実装するか?(実装例)
  96. 96. 96 / 277 今回は、葉ノードと内部ノードの区別をしない ◦ A,B,C,D,Eはどれも列上の項目とする D B E A C
  97. 97. 97 / 277 各ノードは、Δ𝑥 𝐴 というフィールドを持つ D B E A C
  98. 98. 98 / 277 各ノードは、Δ𝑥 𝐴 というフィールドを持つ 各ノードに定めたい値𝑥 𝐴 は、 𝑥𝐴 = Δ𝑥 𝐴 D 𝐴から根までのパス上のノード B E A C
  99. 99. 99 / 277 𝑥 𝐴 = Δ𝑥 𝐷 + Δ𝑥 𝐵 + Δ𝑥 𝐴 𝑥 𝐵 = Δ𝑥 𝐷 + Δ𝑥 𝐵 𝑥 𝐶 = Δ𝑥 𝐷 + Δ𝑥 𝐵 + Δ𝑥 𝐶 𝑥 𝐷 = Δ𝑥 𝐷 D 𝑥 𝐸 = Δ𝑥 𝐷 + Δ𝑥 𝐸 B E A C
  100. 100. 100 / 277 木の回転: 𝑥 𝐴 が保存されるように行う Δ𝑥 ′𝐴 = 𝑥𝐴 − 𝑥𝐵 Δ𝑥 ′𝐵 = 𝑥𝐵 B Δ𝑥 ′𝐶 = 𝑥𝐶 − 𝑥𝐷 Δ𝑥 ′𝐷 = 𝑥𝐷− 𝑥𝐵 Δ𝑥 ′𝐸 = 𝑥𝐸− 𝑥𝐷 A D C E
  101. 101. 101 / 277 木の回転: 𝑥 𝐴 が保存されるように行う Δ𝑥 ′𝐴 = Δ𝑥 𝐴 Δ𝑥 ′𝐵 = Δ𝑥 𝐷 + Δ𝑥 𝐵 B Δ𝑥 ′𝐶 = Δ𝑥 𝐵 + Δ𝑥 𝐶 Δ𝑥 ′𝐷 = −Δ𝑥 𝐵 Δ𝑥 ′𝐸 = Δ𝑥 𝐸 A D C E
  102. 102. 102 / 277 最後に、ノードに値𝑦 𝐴 を 𝑦𝐴 = min 𝑥𝐵 − 𝑥𝐴 𝐴の全ての子孫 𝐵 となるように計算して保持しておく
  103. 103. 103 / 277 最後に、ノードに値𝑦 𝐴 を 𝑦𝐴 = min 𝑥𝐵 − 𝑥𝐴 𝐴の全ての子孫 𝐵 となるように計算して保持しておく これでStarry Sky Tree相当の計算を行えるようになる
  104. 104. 104 / 277 平衡二分木の基本
  105. 105. 105 / 277 平衡二分木の基本:回転操作
  106. 106. 106 / 277 回転操作: 順序を保存したまま木構造を変形
  107. 107. 107 / 277 回転操作: 順序を保存したまま木構造を変形 次のような二分木を考える D B E A C
  108. 108. 108 / 277 回転操作: 順序を保存したまま木構造を変形 次のような二分木を考える 順序: 左の子孫→自分→右の子孫 D B E A C
  109. 109. 109 / 277 回転操作: 順序を保存したまま木構造を変形 次のような二分木を考える 順序: 左の子孫→自分→右の子孫 D この場合は A, B, C, D, E の順番 B E A C
  110. 110. 110 / 277 次のように変形しても順番はA,B,C,D,E D B B E A D A C C E
  111. 111. 111 / 277 次のように変形しても順番はA,B,C,D,E これを「木の回転」と言う D B B E A D A C C E
  112. 112. 112 / 277 次のように変形しても順番はA,B,C,D,E これを「木の回転」と言う うまく回転をすることで、偏りが起きないようにする二 分木を「平衡二分木」と言う ◦ 回転以外の方法で平衡を保つものもある
  113. 113. 113 / 277 平衡二分木の実装方法
  114. 114. 114 / 277 平衡二分木の実装方法 今回は何でもOK! ◦ 赤黒木 ◦ RBST ◦ Treap ◦ Splay木 ◦ などなど…
  115. 115. 115 / 277 この解説ではSplay木の説明をします
  116. 116. 116 / 277 突然ですが、Union Findの復習をします
  117. 117. 117 / 277 突然ですが、Union Findの復習をします A Union Find の効率化テクニック: アクセスした頂点を根へ持っていく B F C D E
  118. 118. 118 / 277 突然ですが、Union Findの復習をします A Union Find の効率化テクニック: アクセスした頂点を根へ持っていく B F C D E
  119. 119. 119 / 277 突然ですが、Union Findの復習をします A Union Find の効率化テクニック: アクセスした頂点を根へ持っていく B F C D E
  120. 120. 120 / 277 突然ですが、Union Findの復習をします A Union Find の効率化テクニック: アクセスした頂点を根へ持っていく B F C D E
  121. 121. 121 / 277 突然ですが、Union Findの復習をします A Union Find の効率化テクニック: アクセスした頂点を根へ持っていく B F C D E
  122. 122. 122 / 277 突然ですが、Union Findの復習をします A Union Find の効率化テクニック: アクセスした頂点を根へ持っていく B F C D E
  123. 123. 123 / 277 同じようなことを、二分探索木でもできないか?
  124. 124. 124 / 277 同じようなことを、二分探索木でもできないか? ◦ →Move-to-root heuristic
  125. 125. 125 / 277 Move-to-root heuristic ◦ 頂点にアクセスしたら、それが根に行くまで繰り返し回転する
  126. 126. 126 / 277 Move-to-root heuristic ◦ 頂点にアクセスしたら、それが根に行くまで繰り返し回転する ◦ そんなので上手くいくわけないだろ!!
  127. 127. 127 / 277 実際ダメ
  128. 128. 128 / 277 実際ダメ E D C B A
  129. 129. 129 / 277 実際ダメ E D C B A
  130. 130. 130 / 277 実際ダメ E D C A B
  131. 131. 131 / 277 実際ダメ E D A C B
  132. 132. 132 / 277 実際ダメ E A D C B
  133. 133. 133 / 277 実際ダメ A E D C B
  134. 134. 134 / 277 実際ダメ この後A, B, C, D, Eの順にアクセスしたら 𝑛 + 𝑛 − 1 + … + 1 = 𝑂 𝑛2 のコストがかかってしまう
  135. 135. 135 / 277 実際ダメ この後A, B, C, D, Eの順にアクセスしたら 𝑛 + 𝑛 − 1 + … + 1 = 𝑂 𝑛2 のコストがかかってしまう どうする?
  136. 136. 136 / 277 解決策: 木の回転を3つに分ける
  137. 137. 137 / 277 解決策: 木の回転を3つに分ける ◦ “zig” step ◦ “zig-zag” step ◦ “zig-zig” step
  138. 138. 138 / 277 (1) “zig”-step
  139. 139. 139 / 277 (1) “zig”-step すぐ上が根の場合 R A
  140. 140. 140 / 277 (1) “zig”-step すぐ上が根の場合 普通に回転する A R
  141. 141. 141 / 277 (2) “zig-zag”-step
  142. 142. 142 / 277 (2) “zig-zag”-step 左→右、またはその逆のとき G P A
  143. 143. 143 / 277 (2) “zig-zag”-step 左→右、またはその逆のとき G 普通に2回回転する A P
  144. 144. 144 / 277 (2) “zig-zag”-step 左→右、またはその逆のとき 普通に2回回転する A P G
  145. 145. 145 / 277 (2) “zig-zag”-step 左→右、またはその逆のとき 普通に2回回転する ここまでは先ほどと同じ
  146. 146. 146 / 277 (3) “zig-zig”-step
  147. 147. 147 / 277 (3) “zig-zig”-step 左→左、またはその逆のとき G P A
  148. 148. 148 / 277 (3) “zig-zig”-step 左→左、またはその逆のとき G 2回ではなく3回回転する P A
  149. 149. 149 / 277 (3) “zig-zig”-step 左→左、またはその逆のとき G 2回ではなく3回回転する A P
  150. 150. 150 / 277 (3) “zig-zig”-step 左→左、またはその逆のとき A 2回ではなく3回回転する G P
  151. 151. 151 / 277 (3) “zig-zig”-step 左→左、またはその逆のとき A 2回ではなく3回回転する P G (ただし、後でこれを2回として扱う)
  152. 152. 152 / 277 Splaying operation ◦ 偏った位置にあるときだけ余計に回転する
  153. 153. 153 / 277 Splaying operation ◦ 偏った位置にあるときだけ余計に回転する ◦ そんなので上手くいくわけないだろ!!
  154. 154. 154 / 277 実は上手くいく
  155. 155. 155 / 277 実は上手くいく 具体的には: 𝑂(log 𝑁) amortized
  156. 156. 156 / 277 実は上手くいく 具体的には: 𝑂(log 𝑁) amortized
  157. 157. 157 / 277 ならし計算量 (amortized time complexity) N個の一連の操作が𝑂(𝑓(𝑁))で行えるとする 𝑓 𝑁 1つ1つの操作は、本当は𝑂( )とは限らない 𝑁 𝑓 𝑁 これを𝑂( )として扱うのが、ならし計算量 𝑁
  158. 158. 158 / 277 ならし計算量のイメージ 操作1 本当の計算量 操作2 操作3 操作4 ならし計算量 操作5
  159. 159. 159 / 277 ならし計算量の向き/不向き
  160. 160. 160 / 277 ならし計算量の向き/不向き 向いているもの ◦ 全体での処理効率が重視されるバッチ型の処理 ◦ 例: プログラミングコンテスト 向いていないもの ◦ リアルタイム性能が重視される処理 ◦ 例: 信号処理
  161. 161. 161 / 277 ならし計算量と平均計算量
  162. 162. 162 / 277 ならし計算量と平均計算量 ◦ この2つは別物!! ◦ ならし計算量 : 時系列上での平均 ◦ 平均計算量 : 確率変数上での平均
  163. 163. 163 / 277 ならし計算量と平均計算量 ◦ この2つは別物!! ◦ ならし計算量 : 時系列上での平均 ◦ 平均計算量 : 確率変数上での平均 ◦ ならし計算量 : 不確定要素は無い!
  164. 164. 164 / 277 Splayのならし計算量の評価
  165. 165. 165 / 277 Splayのならし計算量の評価 「ポテンシャル関数」の概念を導入
  166. 166. 166 / 277 Splayのならし計算量の評価 「ポテンシャル関数」の概念を導入 ◦ 借金みたいなもの
  167. 167. 167 / 277 ポテンシャル関数を用いた計算量の均し(ならし) 𝑎 𝑗 = 𝑡 𝑗 + Φ 𝑗+1 − Φj ◦ 𝑡 𝑗 : その操作の実際の計算量 ◦ Φ 𝑗+1 − Φj : ポテンシャルの増加量 ◦ 𝑎 𝑗 : その操作のならし計算量
  168. 168. 168 / 277 ポテンシャル関数を用いた計算量の均し(ならし) 𝑎 𝑗 = 𝑡 𝑗 + Φ 𝑗+1 − Φj ◦ 𝑡 𝑗 : その操作の実際の計算量 ◦ Φ 𝑗+1 − Φj : ポテンシャルの増加量 ◦ 𝑎 𝑗 : その操作のならし計算量 ポテンシャルの意味 ◦ より大きい: 木はより偏っている ◦ より小さい: 木はより平坦になっている
  169. 169. 169 / 277 ならし計算量の総和をとる 𝑗 𝑎𝑗 = 𝑗 𝑡 𝑗 + Φ 𝑚 − Φ0 ◦ 𝑗 𝑡 𝑗 : 実際の計算量の総和 ◦ Φ 𝑚 − Φ0 : ポテンシャルの総変化量 ◦ 𝑗 𝑎 𝑗 : ならし計算量の総和
  170. 170. 170 / 277 ならし計算量の総和をとる 𝑗 𝑎𝑗 = 𝑗 𝑡 𝑗 + Φ 𝑚 − Φ0 ◦ 𝑗 𝑡 𝑗 : 実際の計算量の総和 ◦ Φ 𝑚 − Φ0 : ポテンシャルの総変化量 ◦ 𝑗 𝑎 𝑗 : ならし計算量の総和 ポテンシャルの総変化量が小さければうまく評価でき る
  171. 171. 171 / 277 Splay木のポテンシャル ◦ Splay木の各頂点の重さを𝑤(𝑥)とする  計算量の見積もり方にあわせて自由に決めてよい ◦ Splay木の頂点のサイズ s 𝑥 = 𝑤(𝑦) 𝑥の全ての子孫 𝑦 ◦ Splay木の頂点のランク 𝑟 𝑥 = log 2 𝑠(𝑥) ◦ Splay木のポテンシャル Φ = 𝑟(𝑥) 全ての頂点 𝑥
  172. 172. 172 / 277 Splay木のポテンシャル: 例
  173. 173. 173 / 277 Splay木のポテンシャル: 例 重さ 𝑤(𝑥) 1 (今回は全て1とする) 1 1 1 1 1 1
  174. 174. 174 / 277 Splay木のポテンシャル: 例 サイズ 𝑠(𝑥) 7 ◦ 部分木の重さの和 5 1 1 3 1 1
  175. 175. 175 / 277 Splay木のポテンシャル: 例 ランク 𝑟 𝑥 = log 2 𝑠(𝑥) 2.8 2.3 0.0 0.0 1.6 0.0 0.0
  176. 176. 176 / 277 Splay木のポテンシャル: 例 ポテンシャル: ランクの総和 Φ = 2.8 + 2.3 + 1.6 = 6.7
  177. 177. 177 / 277 Splay木のポテンシャルの良い性質
  178. 178. 178 / 277 Splay木のポテンシャルの良い性質 … 回転の影響を受ける頂点が少ない ◦ 解析が簡単になる
  179. 179. 179 / 277 アクセス補題 (Access Lemma)
  180. 180. 180 / 277 アクセス補題 (Access Lemma) 𝑥 : 木のノード 𝑡 : 木の根 とするとき 木をsplayする操作一回にかかる時間(回転の回数) は、ならし計算量で 3𝑟 𝑡 − 3𝑟 𝑥 + 1 以下である。
  181. 181. 181 / 277 アクセス補題の証明
  182. 182. 182 / 277 アクセス補題の証明 各回転ステップのならし計算量が 1. “zig”-stepでは 3𝑟 ′ 𝑥 − 3𝑟 𝑥 + 1 以下 2. それ以外では 3𝑟 ′ 𝑥 − 3𝑟(𝑥) 以下 (ただし、𝑟′(𝑥) : 操作後のランク) であることを示す。 そうすると、1のケースに登場する𝑟′(𝑥)は初期の𝑟(𝑡) と等しい(木全体のサイズの対数)ので、合計すると 3𝑟 𝑡 − 3𝑟 𝑥 + 1になる。
  183. 183. 183 / 277 アクセス補題の証明 (1) “zig”-step の場合 𝑟 𝑋 = log 2 (𝑤 𝑋 + 𝑤 𝐴 + 𝑤 𝐵 ) R 𝑟 𝑅 = log 2 (𝑤 𝑋 + 𝑤 𝐴 + 𝑤 𝐵 + 𝑤 𝐶 + 𝑤(𝑅)) X C A B
  184. 184. 184 / 277 アクセス補題の証明 (1) “zig”-step の場合 𝑟 𝑋 = log 2 (𝑤 𝑋 + 𝑤 𝐴 + 𝑤 𝐵 )X 𝑟 ′ 𝑋 = log 2 (𝑤 𝑋 + 𝑤 𝐴 + 𝑤 𝐵 + 𝑤 𝐶 + 𝑤 𝑅 ) 𝑟 𝑅 = log 2 (𝑤 𝑋 + 𝑤 𝐴 + 𝑤 𝐵 + 𝑤 𝐶 + 𝑤(𝑅)) 𝑟 ′ 𝑅 = log 2 (𝑤 𝑅 + 𝑤 𝐵 + A 𝐶 ) R 𝑤 B C
  185. 185. 185 / 277 アクセス補題の証明 (1) “zig”-step の場合 𝑟 𝑋 = log 2 (𝑤 𝑋 + 𝑤 𝐴 + 𝑤 𝐵 ) 𝑟 ′ 𝑋 = log 2 (𝑤 𝑋 + 𝑤 𝐴 + 𝑤 𝐵 + 𝑤 𝐶 + 𝑤 𝑅 ) 𝑟 𝑅 = log 2 (𝑤 𝑋 + 𝑤 𝐴 + 𝑤 𝐵 + 𝑤 𝐶 + 𝑤(𝑅)) 𝑟 ′ 𝑅 = log 2 (𝑤 𝑅 + 𝑤 𝐵 + 𝑤 𝐶 )
  186. 186. 186 / 277 アクセス補題の証明 (1) “zig”-step の場合 𝑟 𝑋 = log 2 (𝑤 𝑋 + 𝑤 𝐴 + 𝑤 𝐵 ) 𝑟 ′ 𝑋 = log 2 (𝑤 𝑋 + 𝑤 𝐴 + 𝑤 𝐵 + 𝑤 𝐶 + 𝑤 𝑅 ) 𝑟 𝑅 = log 2 (𝑤 𝑋 + 𝑤 𝐴 + 𝑤 𝐵 + 𝑤 𝐶 + 𝑤(𝑅)) 𝑟 ′ 𝑅 = log 2 (𝑤 𝑅 + 𝑤 𝐵 + 𝑤 𝐶 ) 𝑟 𝑋 ≤ 𝑟 ′ 𝑋 , 𝑟 ′ 𝑅 ≤ 𝑟(𝑅)
  187. 187. 187 / 277 アクセス補題の証明 (1) “zig”-step の場合 𝑟 𝑋 ≤ 𝑟 ′ 𝑋 , 𝑟 ′ 𝑅 ≤ 𝑟(𝑅) ならし計算量 𝑎 = 𝑡 + Φ′ − Φ = 1 + 𝑟′ 𝑋 + 𝑟′ 𝑅 − 𝑟 𝑋 − 𝑟 𝑅 ≤ 1 + 𝑟′ 𝑋 − 𝑟 𝑋 ≤ 1 + 3𝑟 ′ 𝑋 − 3𝑟 𝑋
  188. 188. 188 / 277 アクセス補題の証明 (2) “zigzig”-step の場合 𝑟 𝑋 = log 2 (𝑤 𝑋 + 𝑠 𝐴 + 𝑠 𝐵 ) G D 𝑟 𝑃 = log 2 (𝑤 𝑋 + 𝑠 𝐴 + 𝑠 𝐵 + 𝑠 𝐶P + 𝑤(𝑃)) 𝑟 𝐺 = X C log 2 (𝑤 𝑋 + 𝑠 𝐴 + 𝑠 𝐵 + 𝑠 𝐶 + 𝑤 𝑃 + 𝑠 𝐷 + 𝑤 𝐺 ) A B
  189. 189. 189 / 277 アクセス補題の証明 (2) “zigzig”-step の場合 𝑟 𝑋 = log 2 (𝑤 𝑋 + 𝑠 𝐴 + 𝑠 𝐵 ) X ′ 𝑋 = 𝑟 log 2 (𝑤 𝑋 + 𝑠 𝐴 + 𝑠 𝐵 + 𝑠 𝐶 + 𝑠 𝐷 + 𝑤 𝑃 + 𝑤 𝐺 ) A P 𝑟 𝑃 = log 2 (𝑤 𝑋 + 𝑠 𝐴 + 𝑠 𝐵 + 𝑠 𝐶 + 𝑤(𝑃)) 𝑟 ′ 𝑃 = log 2 (𝑠 𝐵 + 𝑠 𝐶 + 𝑤 𝑃 + 𝑤 𝐺 ) B G 𝑟 𝐺 = log 2 (𝑤 𝑋 + 𝑠 𝐴 + 𝑠 𝐵 + 𝑠 𝐶 + 𝑤 𝑃 + 𝑠 𝐷 + 𝑤 𝐺 ) 𝑟 ′ 𝐺 = log 2 (𝑠 𝐶 + 𝑠 𝐷 + 𝑤 𝐺 ) C D
  190. 190. 190 / 277 アクセス補題の証明 (2) “zigzig”-step の場合 𝑟 𝑋 = log 2 (𝑤 𝑋 + 𝑠 𝐴 + 𝑠 𝐵 ) 𝑟′ 𝑋 = log 2 (𝑤 𝑋 + 𝑠 𝐴 + 𝑠 𝐵 + 𝑠 𝐶 + 𝑠 𝐷 + 𝑤 𝑃 + 𝑤 𝐺 ) 𝑟 𝑃 = log 2 (𝑤 𝑋 + 𝑠 𝐴 + 𝑠 𝐵 + 𝑠 𝐶 + 𝑤(𝑃)) 𝑟 ′ 𝑃 = log 2 (𝑠 𝐵 + 𝑠 𝐶 + 𝑤 𝑃 + 𝑤 𝐺 ) 𝑟 𝐺 = log 2 (𝑤 𝑋 + 𝑠 𝐴 + 𝑠 𝐵 + 𝑠 𝐶 + 𝑤 𝑃 + 𝑠 𝐷 + 𝑤 𝐺 ) 𝑟 ′ 𝐺 = log 2 (𝑠 𝐶 + 𝑠 𝐷 + 𝑤 𝐺 )
  191. 191. 191 / 277 アクセス補題の証明 (2) “zigzig”-step の場合 𝑟′ 𝑋 = 𝑟 𝐺 , 𝑟′ 𝑋 ≤ 𝑟′ 𝑃 , 𝑟 𝑃 ≤ 𝑟 𝑋
  192. 192. 192 / 277 アクセス補題の証明 (2) “zigzig”-step の場合 𝑟′ 𝑋 = 𝑟 𝐺 , 𝑟′ 𝑃 ≤ 𝑟′ 𝑋 , 𝑟 𝑋 ≤ 𝑟 𝑃 𝑎 = 𝑡 + Φ′ − Φ = 2 + 𝑟′ 𝑋 + 𝑟′ 𝑃 + 𝑟′ 𝐺 − 𝑟 𝑋 − 𝑟 𝑃 − 𝑟 𝐺 ≤ 2 + 𝑟 ′ 𝑋 + 𝑟 ′ 𝐺 − 2𝑟 𝑋
  193. 193. 193 / 277 アクセス補題の証明 (2) “zigzig”-step の場合 2 + 𝑟 ′ 𝑋 + 𝑟 ′ 𝐺 − 2𝑟 𝑋 ≤ 3𝑟 ′ 𝑋 − 3𝑟 𝑋 理由: 𝑟 ′ 𝐺 + 𝑟 𝑋 − 2𝑟 ′ 𝑋 ≤ −2 を示したい。 𝑠′ 𝐺 𝑠 𝑋 ところで左辺はlog 2 + log 2 であり、 𝑠′ 𝑋 𝑠′ 𝑋 log 2 𝑥が上に凸で、𝑠 ′ 𝐺 + 𝑠 𝑋 ≤ 𝑠′(𝑋)なのでこの 値は高々−2 よって不等式は示された。
  194. 194. 194 / 277 アクセス補題の証明 (3) “zigzag”-step の場合 𝑟′ 𝑋 = 𝑟 𝐺 , 𝑟 𝑋 ≤ 𝑟 𝑃 𝑠′ 𝑃 + 𝑠′ 𝐺 ≤ 𝑠′ 𝑋 G X P D P G A X A B C D B C
  195. 195. 195 / 277 アクセス補題の証明 (3) “zigzag”-step の場合 以下(2)と同様
  196. 196. 196 / 277 以上より、Splay操作がならし計算量で𝑂(log 𝑁)であ ることがわかった。 ところで、Splay操作のポテンシャルは高々 𝑂(𝑁 log 𝑁 )なので、全体で𝑂((𝑄 + 𝑁) log 𝑁)でクエリ を処理できることがわかった。
  197. 197. 197 / 277 以上より、Splay操作がならし計算量で𝑂(log 𝑁)であ ることがわかった。 ところで、Splay操作のポテンシャルは高々 𝑂(𝑁 log 𝑁 )なので、全体で𝑂((𝑄 + 𝑁) log 𝑁)でクエリ を処理できることがわかった。 以上、満点解法その1
  198. 198. 198 / 277 満点解法その2 - Link/Cut木
  199. 199. 199 / 277 満点解法その2 - Link/Cut木 Link/Cut木 ◦ 元々、フローアルゴリズムの高速化のためにSleatorとTarjan が考案したもの
  200. 200. 200 / 277 満点解法その2 - Link/Cut木 Link/Cut木 ◦ 元々、フローアルゴリズムの高速化のためにSleatorとTarjan が考案したもの ◦ この問題のために必要な実装は、それよりもはるかに容易
  201. 201. 201 / 277 満点解法その2 - Link/Cut木 Link/Cut木 ◦ 元々、フローアルゴリズムの高速化のためにSleatorとTarjan が考案したもの ◦ この問題のために必要な実装は、それよりもはるかに容易 →Link/Cut木の練習としても適している
  202. 202. 202 / 277 満点解法その2 - Link/Cut木 Link/Cut木 ◦ 元々、フローアルゴリズムの高速化のためにSleatorとTarjan が考案したもの ◦ この問題のために必要な実装は、それよりもはるかに容易 →Link/Cut木の練習としても適している ◦ いろいろなバージョンがあるが、Splay木によるものが使いや すい
  203. 203. 203 / 277 予備知識 – Heavy/Light decomposition
  204. 204. 204 / 277 予備知識 – Heavy/Light decomposition ◦ 木をパスに分割する方法 A B C D E F
  205. 205. 205 / 277 予備知識 – Heavy/Light decomposition ◦ 木をパスに分割する方法 A B C D E F
  206. 206. 206 / 277 予備知識 – Heavy/Light decomposition ◦ 木をパスに分割する方法 変な形の木でも、「パスの木」の形に潰すと安定する
  207. 207. 207 / 277 Splay Treeの世界 列データ Splay Tree 列の畳み込みを効率よく計算
  208. 208. 208 / 277 Splay Treeの世界 列データ Splay Tree 列の畳み込みを効率よく計算
  209. 209. 209 / 277 Heavy/Light decompositionの世界 有向木 列データ Splay Tree 有向木を分解したもの 列の畳み込みを効率よく計算
  210. 210. 210 / 277 Link/Cut Treeの世界 有向木 Link/Cut Tree パスの畳み込みを効率よく計算 列データ Splay Tree 有向木を分解したもの 列の畳み込みを効率よく計算
  211. 211. 211 / 277 Link/Cut Treeの世界 H/L分解 = パスからなる木
  212. 212. 212 / 277 Link/Cut Treeの世界 H/L分解 = パスからなる木 Link/Cut Tree = Splay木からなる木
  213. 213. 213 / 277 Link/Cut Tree の辺は二種類ある ◦ Solid(Heavy) edge ◦ Dashed(Light) edge
  214. 214. 214 / 277 Link/Cut Tree の辺は二種類ある Solid(Heavy) Dashed(Light) 所属 Splay Tree H/L分解の木 分類 二分木 多分木 左右の区別 左右の区別あり なし 親 本当は祖先か子孫 本当の親 子供 本当は祖先か子孫 本当は子孫
  215. 215. 215 / 277 Solid, Dashedの区別
  216. 216. 216 / 277 Solid, Dashedの区別 いずれも、親方向リンクを持つ X L R M
  217. 217. 217 / 277 Solid, Dashedの区別 いずれも、親方向リンクを持つ 親から左方向リンクがあれば、Solid X L R M
  218. 218. 218 / 277 Solid, Dashedの区別 いずれも、親方向リンクを持つ 親から左方向リンクがあれば、Solid 親から右方向リンクがあれば、Solid X L R M
  219. 219. 219 / 277 Solid, Dashedの区別 いずれも、親方向リンクを持つ 親から左方向リンクがあれば、Solid 親から右方向リンクがあれば、Solid X どちらもなければ、Dashed L R M
  220. 220. 220 / 277 Solid, Dashedの区別 いずれも、親方向リンクを持つ 親から左方向リンクがあれば、Solid 親から右方向リンクがあれば、Solid どちらもなければ、Dashed 「右, 左, 親」の3つのリンクだけで構造を保持できる!
  221. 221. 221 / 277 小さな例 A B C F D E
  222. 222. 222 / 277 小さな例 A B C F D E
  223. 223. 223 / 277  小さな例 F B A A B D C C FD E E
  224. 224. 224 / 277  小さな例 B A B F A C FD E DF B A C D C E E
  225. 225. 225 / 277 Link/Cut Treeの操作: splayLC() Link/Cut Tree上では、任意の頂点Xを根に持っていく ことができる ◦ 元の木の構造は変化しないことに注意
  226. 226. 226 / 277 前準備: splay 各Splay Tree上でsplayをすることで、Xから今の根ま でを点線だけで行けるようにする
  227. 227. 227 / 277 前準備: splay B 各Splay Tree上でsplayをすることで、Xから今の根ま F A でを点線だけで行けるようにする D C E
  228. 228. 228 / 277 前準備: splay B 各Splay Tree上でsplayをすることで、Xから今の根ま F A でを点線だけで行けるようにする C D E
  229. 229. 229 / 277 前準備: splay B 各Splay Tree上でsplayをすることで、Xから今の根ま F A でを点線だけで行けるようにする C EからBまで、点 線のみで行ける D ようになる E
  230. 230. 230 / 277 splayLC() のメイン操作: つなぎ変え(expose操作) パスのつなぎ変え操作を行う 元の木ではこんな感じ
  231. 231. 231 / 277 A splayLC() のメイン操作: つなぎ変え(expose操作) B パスのつなぎ変え操作を行う 元の木ではこんな感じ C F D E
  232. 232. 232 / 277 A splayLC() のメイン操作: つなぎ変え(expose操作) B パスのつなぎ変え操作を行う 元の木ではこんな感じ C F D E
  233. 233. 233 / 277 A splayLC() のメイン操作: つなぎ変え(expose操作) B パスのつなぎ変え操作を行う 元の木ではこんな感じ C F D E
  234. 234. 234 / 277 splayLC() のメイン操作: つなぎ変え(expose操作) パスのつなぎ変え操作を行う Link/Cut 木でも、左向きのSolid辺を付け替えるだけ
  235. 235. 235 / 277 splayLC() のメイン操作: B つなぎ変え(expose操作) F パスのつなぎ変え操作を行う A Link/Cut 木でも、左向きのSolid辺を付け替えるだけ C D E
  236. 236. 236 / 277 splayLC() のメイン操作: B つなぎ変え(expose操作) F パスのつなぎ変え操作を行う A Link/Cut 木でも、左向きのSolid辺を付け替えるだけ C D E
  237. 237. 237 / 277 B splayLC() のメイン操作: つなぎ変え(expose操作) C パスのつなぎ変え操作を行う A E Link/Cut 木でも、左向きのSolid辺を付け替えるだけ D F
  238. 238. 238 / 277 左向きの辺をつなぎ替えるだけで、Eが一番上の木に 所属するようになった
  239. 239. 239 / 277 左向きの辺をつなぎ替えるだけで、Eが一番上の木に 所属するようになった 最後にもう1度splay()操作を行うことで、Link/Cut Treeの一番上の根にEが来る
  240. 240. 240 / 277 L/C木のsplayLC()はSplay Treeの解析を少し応用す ると、対数時間であることが言える
  241. 241. 241 / 277 L/C木のsplayLC()はSplay Treeの解析を少し応用す ると、対数時間であることが言える 1回ごとのsplay()操作が対数時間であることは既に わかっている
  242. 242. 242 / 277 L/C木のsplayLC()はSplay Treeの解析を少し応用す ると、対数時間であることが言える 1回ごとのsplay()操作が対数時間であることは既に わかっている しかし実際にはsplay()操作が𝑘回呼ばれている ◦ 𝑘は、パス分割された木の上での深さ
  243. 243. 243 / 277 ポテンシャルの定義 ◦ サイズ = solid/dashedに関わらず、子孫になっている頂点の 数 ◦ ランク = その対数 ◦ ポテンシャル = ランクの総和の2倍 として定める
  244. 244. 244 / 277 Splay Treeのならし計算量は 1 + 3𝑟 𝑡 − 3𝑟(𝑥) だっ た 今回のならし計算量は𝑘 + 6𝑟 𝑡 − 6𝑟(𝑥)になる ◦ 「Splayが𝑘回呼ばれる」という認識を改めてみる ◦ Splayは根に向かって順番に呼ばれるということを考慮すると、 「Splayが1回呼ばれるが、途中でk回、強制的にzigステップを 使われるかもしれない」と考えることができる ◦ 係数が2倍なのはポテンシャルの定義を変えたから
  245. 245. 245 / 277 余った定数項𝑘の回収 Expose操作のあとに1回行うsplay操作: k回の回転を 行う。 ポテンシャルの定義を2倍にしたので、splayの回転操 作1回につき1の追加コストを課しても問題ない
  246. 246. 246 / 277 ならしコスト6 log 2 𝑁のsplay操作を2回呼んでいるの で、splayLC()のならし計算量は12 log 2 𝑁 = 𝑂(log 𝑁) であるとわかった。
  247. 247. 247 / 277 AとBのLCAを求める。
  248. 248. 248 / 277 AとBのLCAを求めるには、まず 1. Bに対してsplayLC()を行う 2. Aに対してsplayLC()を行う このとき、Bは浅い位置にいる。 ◦ Splay Treeに対するSplay操作1回で、他の頂点の深さは高々 2段しか下がらないので、この時点でBは深さ高々4程度。
  249. 249. 249 / 277 AとBの位置関係に基いて条件分岐
  250. 250. 250 / 277 AとBの位置関係に基いて条件分岐 (1) BがAの左側にある場合 ◦ この場合は、BはAの子孫ということになるので、AとBのLCA はAになる。 (2) BがAの右側にある場合 ◦ 次のページへ
  251. 251. 251 / 277 BがAの右側にある場合の条件分岐 (1) BがAと同じSplay Treeに属する場合 ◦ この場合は、AはBの子孫ということになるので、AとBのLCA はBになる。
  252. 252. 252 / 277 BがAの右側にある場合の条件分岐 (1) BがAと同じSplay Treeに属する場合 ◦ この場合は、AはBの子孫ということになるので、AとBのLCA はBになる。 (2) BがAと異なるSplay Treeに属する場合 ◦ 一番一般的な場合。 ◦ Bから上に辿り、Aと同じSplay Treeに到達したところの頂点が、 AとBのLCAになる。
  253. 253. 253 / 277 BがAの右側にある場合の条件分岐 (1) BがAと同じSplay Treeに属する場合 ◦ この場合は、AはBの子孫ということになるので、AとBのLCA はBになる。 (2) BがAと異なるSplay Treeに属する場合 ◦ 一番一般的な場合。 ◦ Bから上に辿り、Aと同じSplay Treeに到達したところの頂点が、 AとBのLCAになる。 これでLCAは求められた。
  254. 254. 254 / 277 クエリ1,2番に対応する「接続」「切断」は、 Link/Cut Treeの”link”, “cut” に対応する。
  255. 255. 255 / 277 クエリ1,2番に対応する「接続」「切断」は、 Link/Cut Treeの”link”, “cut” に対応する。 (1) Link操作 – AをBの子にする ◦ AとBをsplayLC()しておいてから、Aの親として(dashedで)Bを 設定するだけ。 ◦ 計算量: AとBがLink/Cut Treeにおける根にあるので、Bのサ イズが高々𝑁増える程度。これによってポテンシャルは 𝑂(log 𝑁) しか増えない。
  256. 256. 256 / 277 クエリ1,2番に対応する「接続」「切断」は、 Link/Cut Treeの”link”, “cut” に対応する。 (2) Cut操作 – Aを親から切り離す ◦ AをsplayLC()してからAの右の子を切り離す。 ◦ 計算量:ポテンシャルは明らかに減っている。
  257. 257. 257 / 277 以上がLink/Cut Treeによる満点解法。
  258. 258. 258 / 277 Euler Tour Tree と Link/Cut Tree は動的木の筆頭
  259. 259. 259 / 277 Euler Tour Tree と Link/Cut Tree は動的木の筆頭 今回はどちらを選ぶべきだったか?
  260. 260. 260 / 277 Euler Tour Tree と Link/Cut Tree は動的木の筆頭 今回はどちらを選ぶべきだったか? (他の問題は解き終わっているとして)
  261. 261. 261 / 277 Euler Tour Tree ◦ 知識: ◦ 実装: Link/Cut Tree ◦ 知識: ◦ 実装:
  262. 262. 262 / 277 Euler Tour Tree ◦ 知識: 過去にも出題済みの知識の組合せ。 ◦ 実装: Link/Cut Tree ◦ 知識: ◦ 実装:
  263. 263. 263 / 277 Euler Tour Tree ◦ 知識: 過去にも出題済みの知識の組合せ。 ◦ 実装: 組み合わせてはいけないものを組み合わせてしまった 感じ Link/Cut Tree ◦ 知識: ◦ 実装:
  264. 264. 264 / 277 Euler Tour Tree ◦ 知識: 過去にも出題済みの知識の組合せ。 ◦ 実装: 組み合わせてはいけないものを組み合わせてしまった 感じ Link/Cut Tree ◦ 知識: 必須 ◦ 実装:
  265. 265. 265 / 277 Euler Tour Tree ◦ 知識: 過去にも出題済みの知識の組合せ。 ◦ 実装: 組み合わせてはいけないものを組み合わせてしまった 感じ Link/Cut Tree ◦ 知識: 必須 ◦ 実装: 頂点にデータを持たせなくてよいなど、この問題におい ては極めて有利
  266. 266. 266 / 277 Euler Tour Tree ◦ 知識: 過去にも出題済みの知識の組合せ。 ◦ 実装: 組み合わせてはいけないものを組み合わせてしまった 感じ Link/Cut Tree ◦ 知識: 必須 ◦ 実装: 頂点にデータを持たせなくてよいなど、この問題におい ては極めて有利 知っているならLink/Cut を書くべきだったかもしれな い
  267. 267. 267 / 277 Link/Cutを学ぶべきか?
  268. 268. 268 / 277 Link/Cutを学ぶべきか? ◦ Link/Cutでなければ出来ない、という問題は、恐らくない
  269. 269. 269 / 277 Link/Cutを学ぶべきか? ◦ Link/Cutでなければ出来ない、という問題は、恐らくない ◦ しかし、Link/Cutを使うと有利な問題は実際に存在している
  270. 270. 270 / 277 qnighyからの提案
  271. 271. 271 / 277 qnighyからの提案 ◦ 合宿参加者の大半にとっては、Link/Cut Treeを習得するコ ストが高くつく上に、他の学習をしたほうがずっと為になると 思う。
  272. 272. 272 / 277 qnighyからの提案 ◦ 合宿参加者の大半にとっては、Link/Cut Treeを習得するコ ストが高くつく上に、他の学習をしたほうがずっと為になると 思う。 ◦ より上位の人や、単純に興味があるという人に関しては、こ の限りではない。
  273. 273. 273 / 277 qnighyからの提案 ◦ 合宿参加者の大半にとっては、Link/Cut Treeを習得するコ ストが高くつく上に、他の学習をしたほうがずっと為になると 思う。 ◦ より上位の人や、単純に興味があるという人に関しては、こ の限りではない。 ◦ いずれにせよ、学習するつもりなら、身に付けるために問題 を解くべきだろう。
  274. 274. 274 / 277 JOI2010春合宿 Day4 “Highway” JOI2012本選 問題5 “Festivals in JOI Kingdom” IOI2011 Day2 “Elephants” IJPC2012 Day3 “Animals2”
  275. 275. 275 / 277 完全制覇・ツリー上でのクエリ処理技法 [iwiwi] http://topcoder.g.hatena.ne.jp/iwiwi/20111205/13 23099376 プログラミングコンテストでのデータ構造 2 ~動的木 編~ [iwiwi] http://www.slideshare.net/iwiwi/2-12188845 蟻本 [iwiwi]
  276. 276. 276 / 277 Daniel D. Sleator and Robert E. Tarjan, A Data Structure for Dynamic Trees, Journal of Computer and System Sciences, Volume 26 Issue 3, June 1983, pp. 362 – 391 Daniel D. Sleator and Robert E. Tarjan, Self-adjusting binary search trees, Journal of the ACM, Volume 32 Issue 3, July 1985, pp. 652 – 686
  277. 277. 277 / 277121086420 0 10 20 30 40 50 60 70 80 90 100

×