SlideShare una empresa de Scribd logo
1 de 277
Descargar para leer sin conexión
1 / 277




               Masaki Hara (qnighy)
2013年 情報オリンピック春期トレーニング合宿にて
2 / 277




 有向木がたくさんあります
 以下のクエリに高速で答えてください
1. Aの親をBにする
     ◦ Aは木の根で、BはAの子孫ではない
2.   Aを親から切り離して木の根にする
3.   A,Bが同じ木に属するか判定し、
     同じ木に属する場合はLCAを求める
3 / 277

                                   K

   有向木がたくさんあります
                                   D


                       B       E       I

               F           A       H       C


       J   L       G
4 / 277

                                   K

   有向木がたくさんあります
   以下のクエリに高速で答えてください              D


                       B       E       I

               F           A       H       C


       J   L       G
5 / 277

                                      K

   1. Fの親をBにする
                                      D


                          B       E       I

                  F           A       H       C


        J    L        G
6 / 277

                                      K

   1. Fの親をBにする
                                      D


                          B       E       I

                  F           A       H       C


        J    L        G
7 / 277

                                     K

   1. Eの親をDにする
                                     D


                         B       E       I

                 F           A       H       C


        J    L       G
8 / 277

                                     K

   1. Eの親をDにする
                                     D


                         B       E       I

                 F           A       H       C


        J    L       G
9 / 277

                                    K

   2. Iを親から切り離して根にする
                                    D


                        B       E       I

                F           A       H       C


        J   L       G
10 / 277

                                    K

   2. Iを親から切り離して根にする
                                    D


                        B       E       I

                F           A       H       C


        J   L       G
11 / 277

                                    K

   2. Lを親から切り離して根にする
                                    D


                        B       E       I

                F           A       H       C


        J   L       G
12 / 277

                                    K

   2. Lを親から切り離して根にする
                                    D


                        B       E       I

                F           A       H       C


        J   L       G
13 / 277

                                     K

   3. GとHのLCAを求める
                                     D


                         B       E       I

                 F           A       H       C


        J    L       G
14 / 277

                                        K

   3. GとHのLCAを求める
    ◦ LCA: 最小共通先祖
                                        D


                            B       E       I

                    F           A       H       C


         J     L        G
15 / 277




   頂点数 𝑁 ≤ 5000
   クエリ数 𝑄 ≤ 5000
16 / 277




   各頂点は親リンクを覚えておく
   クエリ1,2に対しては普通に答える


                 B

             F
17 / 277

                                   K

   各頂点は親リンクを覚えておく
   クエリ3に対しては                      D


                       B       E       I

               F           A       H       C


       J   L       G
18 / 277

                                     K

   各頂点は親リンクを覚えておく
   クエリ3に対しては                        D
    ◦ Gから根に向かって辿る

                         B       E       I

                 F           A       H       C


        J    L       G
19 / 277

                                     K

   各頂点は親リンクを覚えておく
   クエリ3に対しては                        D
    ◦ Gから根に向かって辿る
    ◦ Hから根に向かって辿る
                         B       E       I

                 F           A       H       C


        J    L       G
20 / 277

                                K

   各頂点は親リンクを覚えておく
   クエリ3に対しては                   D
    ◦ Gから根に向かって辿る
    ◦ Hから根に向かって辿る
    ◦ 並べる               B   E

               F                H


                    G
21 / 277




   各頂点は親リンクを覚えておく
   クエリ3に対しては
    ◦ Gから根に向かって辿る
    ◦ Hから根に向かって辿る
    ◦ 並べる


     K      D       B   F   G


     K      D       E   H
22 / 277




   各頂点は親リンクを覚えておく
   クエリ3に対しては
    ◦   Gから根に向かって辿る
    ◦   Hから根に向かって辿る
    ◦   根からの順番で並べる
    ◦   一致する中で最も後ろのものを選ぶ

        K     D     B      F   G


        K     D     E      H
23 / 277




   各頂点は親リンクを覚えておく
   クエリ3に対しては
    ◦   Gから根に向かって辿る
    ◦   Hから根に向かって辿る
    ◦   根からの順番で並べる
    ◦   根が一致しないときは-1
24 / 277




   頂点数 𝑁 ≤ 5000
   クエリ数 𝑄 ≤ 5000

   計算量は𝑂(𝑁𝑄)なので間に合う
25 / 277




   頂点数 𝑁 ≤ 106
   クエリ数 𝑄 ≤ 106
   辺の削除は行われない
26 / 277




   CがAとBのLCA
                    C



                    D       F


                A       B       E
27 / 277




   CがAとBのLCA
    ↓辺を追加           C



                    D       F


                A       B       E
28 / 277




   CがAとBのLCA
    ↓辺を追加            C
   Cは依然としてAとBのLCA


                     D       F


              A          B       E
29 / 277




   CがAとBのLCA
    ↓辺を追加
   Cは依然としてAとBのLCA

   最終的にできる木の上でLCAを計算できればよい
30 / 277




   木の嬉しい順序(DFS順序)
    ◦ Preorder –頂点に入るときに記録する順序

                                 A
   A, B, D, E, C, F
                            B        C

                        D        E       F
31 / 277




   木の嬉しい順序(DFS順序)
    ◦ Postorder – 頂点から出るときに記録する順序

                                 A
   D, E, B, F, C, A
                             B       C

                        D        E       F
32 / 277




   木の嬉しい順序(DFS順序)
    ◦ Euler Tour
      頂点から入るときに記録し、
      頂点から出るときにも
                               A
        自分の親を記録する順序
                           B       C

                       D       E       F
33 / 277




   木の嬉しい順序(DFS順序)
    ◦ Euler Tour
      頂点から入るときに記録し、
      頂点から出るときにも
                                A
        自分の親を記録する順序
                            B       C

                       D        E       F
                       A,
34 / 277




   木の嬉しい順序(DFS順序)
    ◦ Euler Tour
      頂点から入るときに記録し、
      頂点から出るときにも
                               A
        自分の親を記録する順序
                           B       C

                       D       E       F
                       A, B,
35 / 277




   木の嬉しい順序(DFS順序)
    ◦ Euler Tour
      頂点から入るときに記録し、
      頂点から出るときにも
                                  A
        自分の親を記録する順序
                           B          C

                       D          E       F
                       A, B, D,
36 / 277




   木の嬉しい順序(DFS順序)
    ◦ Euler Tour
      頂点から入るときに記録し、
      頂点から出るときにも
                                 A
        自分の親を記録する順序
                           B         C

                       D        E        F
                       A, B, D, B,
37 / 277




   木の嬉しい順序(DFS順序)
    ◦ Euler Tour
      頂点から入るときに記録し、
      頂点から出るときにも
                                 A
        自分の親を記録する順序
                           B           C

                       D        E          F
                       A, B, D, B, E
38 / 277




   木の嬉しい順序(DFS順序)
    ◦ Euler Tour
      頂点から入るときに記録し、
      頂点から出るときにも
                                  A
        自分の親を記録する順序
                            B              C

                       D         E             F
                       A, B, D, B, E, B,
39 / 277




   木の嬉しい順序(DFS順序)
    ◦ Euler Tour
      頂点から入るときに記録し、
      頂点から出るときにも
                                  A
        自分の親を記録する順序
                           B            C

                       D         E            F
                       A, B, D, B, E, B, A,
40 / 277




   木の嬉しい順序(DFS順序)
    ◦ Euler Tour
      頂点から入るときに記録し、
      頂点から出るときにも
                                  A
        自分の親を記録する順序
                           B            C

                       D         E            F
                       A, B, D, B, E, B, A,
                       C,
41 / 277




   木の嬉しい順序(DFS順序)
    ◦ Euler Tour
      頂点から入るときに記録し、
      頂点から出るときにも
                                  A
        自分の親を記録する順序
                           B            C

                       D         E            F
                       A, B, D, B, E, B, A,
                       C, F,
42 / 277




   木の嬉しい順序(DFS順序)
    ◦ Euler Tour
      頂点から入るときに記録し、
      頂点から出るときにも
                                  A
        自分の親を記録する順序
                           B            C

                       D         E            F
                       A, B, D, B, E, B, A,
                       C, F, C,
43 / 277




   木の嬉しい順序(DFS順序)
    ◦ Euler Tour
      頂点から入るときに記録し、
      頂点から出るときにも
                                  A
        自分の親を記録する順序
                           B            C

                       D         E            F
                       A, B, D, B, E, B, A,
                       C, F, C, A
44 / 277




   木の嬉しい順序(DFS順序)
    ◦ Euler Tour
      木の辺を、行きと帰りの2つの辺から
       なるとみなすときの                      A
       オイラー閉路に対応する

                               B            C

                       D             E            F
                           A, B, D, B, E, B, A,
                           C, F, C, A
45 / 277




   木の嬉しい順序(DFS順序)
    ◦ Euler Tour
      木の辺を、行きと帰りの2つの辺から
       なるとみなすときの
       オイラー閉路に対応する
      オイラー閉路 (Euler Tour) : 全ての辺を1度ずつ通る閉路
        オイラー路はケーニヒスベルクの橋問題で有名




                          Wikipediaより。 CC3.0-BY-SA
46 / 277




   Euler TourによるLCAの計算




                                  A

                              B       C

                          D       E       F
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 / 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 / 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 / 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 / 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 / 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 / 277




   正当性
54 / 277




   正当性: CがAとBのLCAのとき
    ◦ Euler Tour上でCは[A,B]に含まれる
    ◦ Euler Tour上で[A,B]に含まれるのはCの部分木
   を言えばよい
55 / 277




   正当性(1): Euler Tour上でCは[A,B]に含まれる
    ◦ AからBに行くにはCを経由しないといけない(LCAの性質より)
    ◦ ので当たり前
56 / 277




   正当性(2): Euler Tour上で[A,B]に含まれるのは
    Cの部分木
    ◦ Euler Tourにおいて部分木は連続した部分列として現れる
    ◦ ので当たり前
57 / 277




   LCAを求めて終わり?
58 / 277




   LCAを求めて終わり?
    ◦ あと少しだけやることがあります
59 / 277




   「削除がない場合の利点」の考察を思い出す
60 / 277




   「削除がない場合の利点」の考察を思い出す
   LCAが存在するなら、最終的な木の上で計算すれば
    よい
61 / 277




   「削除がない場合の利点」の考察を思い出す
   LCAが存在するなら、最終的な木の上で計算すれば
    よい
62 / 277




   A, Bが同じ木上にあるかどうかの判定が必要
63 / 277




   A, Bが同じ木上にあるかどうかの判定が必要

    ですが
64 / 277




   A, Bが同じ木上にあるかどうかの判定が必要

    ですが

    辺の追加クエリしかないのでUnionFindでよい
    ということはすぐにわかると思います
65 / 277




   頂点数 𝑁 ≤ 106
   クエリ数 𝑄 ≤ 106
   辺の削除は行われない

   𝑂(𝑁 + 𝑄 log 𝑁) なので間に合う
66 / 277




   ここまでの両方を実装すれば40点
67 / 277




   ここまでの両方を実装すれば40点

   複数のアルゴリズムを条件によって使い分けるテクは
    さすがに使っていると思います
68 / 277




   頂点数 𝑁 ≤ 106
   クエリ数 𝑄 ≤ 106
69 / 277




   頂点数 𝑁 ≤ 106
   クエリ数 𝑄 ≤ 106
   削除クエリもある
70 / 277




   追加も削除もある場合の頻出テク
71 / 277




   追加も削除もある場合の頻出テク
    ◦ クエリの(平方)分割
    ◦ がんばって動的になんとかする
72 / 277




   追加も削除もある場合の頻出テク

    ◦ がんばって動的になんとかする
73 / 277




   追加も削除もある場合の頻出テク

    ◦ がんばって動的になんとかする
74 / 277




   木が静的な場合のLCA (復習)
75 / 277




   木が静的な場合のLCA (復習)
    ◦ Euler Tour上で必要とされるクエリは以下の通り
76 / 277




   木が静的な場合のLCA (復習)
    ◦ Euler Tour上で必要とされるクエリは以下の通り
    1. 区間の最小値をとる
77 / 277




   木が静的な場合のLCA (復習)
    ◦ Euler Tour上で必要とされるクエリは以下の通り
    1. 区間の最小値をとる
    ◦ RMQで実現可能
78 / 277




   木が動的な場合のLCA (絶望)
    ◦ Euler Tour上で必要とされるクエリは以下の通り
    1. 区間の最小値をとる
    2.
    ◦ RMQで実現可能な気がする
79 / 277




   木が動的な場合のLCA (絶望)
    ◦ Euler Tour上で必要とされるクエリは以下の通り
    1. 区間の最小値をとる
    2. 列の連結をする
    3.
    ◦ RMQで実現可能な気がする
80 / 277




   木が動的な場合のLCA (絶望)
    ◦ Euler Tour上で必要とされるクエリは以下の通り
    1. 区間の最小値をとる
    2. 列の連結をする
    3. 列の分割をする
    4.
    ◦ RMQで実現可能な気がする
81 / 277




   木が動的な場合のLCA (絶望)
    ◦ Euler Tour上で必要とされるクエリは以下の通り
    1. 区間の最小値をとる
    2. 列の連結をする
    3. 列の分割をする
    4. それだけ?
82 / 277




   木が動的な場合のLCA (絶望)
    ◦ Euler Tour上で必要とされるクエリは以下の通り
    1. 区間の最小値をとる
    2. 列の連結をする
    3. 列の分割をする
    4. 区間に値を足す
83 / 277




   木が動的な場合のLCA (絶望)
    ◦ Euler Tour上で必要とされるクエリは以下の通り
    1. 区間の最小値をとる
    2. 列の連結をする
    3. 列の分割をする
    4. 区間に値を足す
    ◦ この業界では「Starry Sky木」として知られているもの
84 / 277




   木が動的な場合のLCA (絶望)
    ◦ Euler Tour上で必要とされるクエリは以下の通り
    1. 区間の最小値をとる
    2. 列の連結をする
    3. 列の分割をする
    4. 区間に値を足す
    ◦ この業界では「Starry Sky木」として知られているもの
      を平衡二分木として実装する必要がある (絶望)
85 / 277




   木が動的な場合のLCA (絶望)
    ◦ Euler Tour上で必要とされるクエリは以下の通り
    1. 区間の最小値をとる
    2. 列の連結をする
    3. 列の分割をする
    4. 区間に値を足す
    ◦ この業界では「Starry Sky木」として知られているもの
      を平衡二分木として実装する必要がある (絶望)
      しかもmerge/splitベースで
86 / 277




   平衡二分木の中身は後回し
87 / 277




   平衡二分木の中身は後回し
   平衡二分木を使った具体的な実装方法
88 / 277




   木の各頂点ごとに、Euler Tourのためのノードを2つ
    用意する(𝑆 𝐴 , 𝐺 𝐴 )
    ◦ 𝑆 𝐴 上には頂点Aの番号と、その深さが記録されている
    ◦ 𝐺 𝐴 上には頂点Aの親Pの番号と、その深さが記録されている
    ◦ Aが根のときは𝑆 𝐴 のみ使う
                       A        A
                                    𝐺𝐵
                           𝑆𝐴
                       B        B
89 / 277




   木の連結                                 A
                                            Depth 0



                            B                     C
                               Depth 0               Depth 1



                   D                 E  Depth 1
                                                         F
                       Depth 1
           𝑆𝐵 𝐵 , 𝑆𝐷   𝐷 , 𝐺 𝐷 𝐵 , 𝑆 𝐸 𝐸 , 𝐺 𝐸 (𝐵)          Depth 2
                                       𝑆 𝐴 𝐴 , 𝑆 𝐶 𝐶 , 𝑆 𝐹 𝐹 , 𝐺 𝐹 𝐶 , 𝐺 𝐹 (𝐴)
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 / 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 / 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 / 277




   木の削除: 追加のときと逆操作
94 / 277




   平衡Starry Sky Treeがあればよいことがわかった
95 / 277




   平衡Starry Sky Treeがあればよいことがわかった
   ではどのように実装するか?(実装例)
96 / 277




   今回は、葉ノードと内部ノードの区別をしない
    ◦ A,B,C,D,Eはどれも列上の項目とする


                           D


                       B       E


                   A       C
97 / 277




   各ノードは、Δ𝑥 𝐴 というフィールドを持つ


                         D


                     B       E


                 A       C
98 / 277




   各ノードは、Δ𝑥 𝐴 というフィールドを持つ
   各ノードに定めたい値𝑥 𝐴 は、
       𝑥𝐴 =                      Δ𝑥 𝐴
                                        D
              𝐴から根までのパス上のノード



                                  B              E


                             A          C
99 / 277




   𝑥 𝐴 = Δ𝑥 𝐷 + Δ𝑥 𝐵 + Δ𝑥 𝐴
   𝑥 𝐵 = Δ𝑥 𝐷 + Δ𝑥 𝐵
   𝑥 𝐶 = Δ𝑥 𝐷 + Δ𝑥 𝐵 + Δ𝑥 𝐶
   𝑥 𝐷 = Δ𝑥 𝐷                         D
   𝑥 𝐸 = Δ𝑥 𝐷 + Δ𝑥 𝐸

                                   B            E


                               A       C
100 / 277




   木の回転: 𝑥 𝐴 が保存されるように行う

   Δ𝑥 ′𝐴 =   𝑥𝐴 − 𝑥𝐵
   Δ𝑥 ′𝐵 =   𝑥𝐵                B
   Δ𝑥 ′𝐶 =   𝑥𝐶 − 𝑥𝐷
   Δ𝑥 ′𝐷 =   𝑥𝐷− 𝑥𝐵
   Δ𝑥 ′𝐸 =   𝑥𝐸− 𝑥𝐷        A        D


                                C         E
101 / 277




   木の回転: 𝑥 𝐴 が保存されるように行う

   Δ𝑥 ′𝐴 = Δ𝑥 𝐴
   Δ𝑥 ′𝐵 = Δ𝑥 𝐷 + Δ𝑥 𝐵         B
   Δ𝑥 ′𝐶 = Δ𝑥 𝐵 + Δ𝑥 𝐶
   Δ𝑥 ′𝐷 = −Δ𝑥 𝐵
   Δ𝑥 ′𝐸 = Δ𝑥 𝐸            A        D


                                C         E
102 / 277




   最後に、ノードに値𝑦 𝐴 を
   𝑦𝐴 =    min    𝑥𝐵 − 𝑥𝐴
         𝐴の全ての子孫 𝐵
   となるように計算して保持しておく
103 / 277




   最後に、ノードに値𝑦 𝐴 を
   𝑦𝐴 =    min    𝑥𝐵 − 𝑥𝐴
         𝐴の全ての子孫 𝐵
   となるように計算して保持しておく

   これでStarry Sky Tree相当の計算を行えるようになる
104 / 277




   平衡二分木の基本
105 / 277




   平衡二分木の基本:回転操作
106 / 277




   回転操作: 順序を保存したまま木構造を変形
107 / 277




   回転操作: 順序を保存したまま木構造を変形
   次のような二分木を考える
                       D


                     B         E


                 A       C
108 / 277




   回転操作: 順序を保存したまま木構造を変形
   次のような二分木を考える
   順序: 左の子孫→自分→右の子孫   D


                     B         E


                 A       C
109 / 277




   回転操作: 順序を保存したまま木構造を変形
   次のような二分木を考える
   順序: 左の子孫→自分→右の子孫   D

   この場合は A, B, C, D, E の順番
                              B         E


                          A       C
110 / 277




   次のように変形しても順番はA,B,C,D,E


                D            B


        B           E   A        D


    A       C                C       E
111 / 277




   次のように変形しても順番はA,B,C,D,E
   これを「木の回転」と言う

                D            B


        B           E   A        D


    A       C                C       E
112 / 277




   次のように変形しても順番はA,B,C,D,E
   これを「木の回転」と言う

   うまく回転をすることで、偏りが起きないようにする二
    分木を「平衡二分木」と言う
    ◦ 回転以外の方法で平衡を保つものもある
113 / 277




   平衡二分木の実装方法
114 / 277




   平衡二分木の実装方法

   今回は何でもOK!
    ◦   赤黒木
    ◦   RBST
    ◦   Treap
    ◦   Splay木
    ◦   などなど…
115 / 277




   この解説ではSplay木の説明をします
116 / 277




   突然ですが、Union Findの復習をします
117 / 277




   突然ですが、Union Findの復習をします
                                    A
   Union Find の効率化テクニック:
   アクセスした頂点を根へ持っていく
                            B                   F


                       C        D


                                        E
118 / 277




   突然ですが、Union Findの復習をします
                                    A
   Union Find の効率化テクニック:
   アクセスした頂点を根へ持っていく
                            B                   F


                       C        D


                                        E
119 / 277




   突然ですが、Union Findの復習をします
                                    A
   Union Find の効率化テクニック:
   アクセスした頂点を根へ持っていく
                            B                   F


                       C        D


                                        E
120 / 277




   突然ですが、Union Findの復習をします
                                    A
   Union Find の効率化テクニック:
   アクセスした頂点を根へ持っていく
                            B                   F


                       C        D


                                        E
121 / 277




   突然ですが、Union Findの復習をします
                                    A
   Union Find の効率化テクニック:
   アクセスした頂点を根へ持っていく
                            B                   F


                       C        D


                                        E
122 / 277




   突然ですが、Union Findの復習をします
                                    A
   Union Find の効率化テクニック:
   アクセスした頂点を根へ持っていく
                            B                   F


                       C        D


                                        E
123 / 277




   同じようなことを、二分探索木でもできないか?
124 / 277




   同じようなことを、二分探索木でもできないか?
    ◦ →Move-to-root heuristic
125 / 277




   Move-to-root heuristic
    ◦ 頂点にアクセスしたら、それが根に行くまで繰り返し回転する
126 / 277




   Move-to-root heuristic
    ◦ 頂点にアクセスしたら、それが根に行くまで繰り返し回転する

    ◦ そんなので上手くいくわけないだろ!!
127 / 277




   実際ダメ
128 / 277




   実際ダメ                   E


                       D



                   C


               B


           A
129 / 277




   実際ダメ                   E


                       D



                   C


               B


           A
130 / 277




   実際ダメ               E


                   D



               C


           A


               B
131 / 277




   実際ダメ               E


                   D



           A


               C


           B
132 / 277




   実際ダメ                   E


                   A


                       D


               C


           B
133 / 277




   実際ダメ               A


                           E


                   D


               C


           B
134 / 277




   実際ダメ
   この後A, B, C, D, Eの順にアクセスしたら
           𝑛 + 𝑛 − 1 + … + 1 = 𝑂 𝑛2
   のコストがかかってしまう
135 / 277




   実際ダメ
   この後A, B, C, D, Eの順にアクセスしたら
           𝑛 + 𝑛 − 1 + … + 1 = 𝑂 𝑛2
   のコストがかかってしまう

   どうする?
136 / 277




   解決策: 木の回転を3つに分ける
137 / 277




   解決策: 木の回転を3つに分ける
    ◦ “zig” step
    ◦ “zig-zag” step
    ◦ “zig-zig” step
138 / 277




   (1) “zig”-step
139 / 277




   (1) “zig”-step
   すぐ上が根の場合
                         R


                     A
140 / 277




   (1) “zig”-step
   すぐ上が根の場合
   普通に回転する          A


                         R
141 / 277




   (2) “zig-zag”-step
142 / 277




   (2) “zig-zag”-step
   左→右、またはその逆のとき
                             G


                    P


                         A
143 / 277




   (2) “zig-zag”-step
   左→右、またはその逆のとき
                          G
   普通に2回回転する

                      A


                  P
144 / 277




   (2) “zig-zag”-step
   左→右、またはその逆のとき
   普通に2回回転する          A


                  P        G
145 / 277




   (2) “zig-zag”-step
   左→右、またはその逆のとき
   普通に2回回転する

   ここまでは先ほどと同じ
146 / 277




   (3) “zig-zig”-step
147 / 277




   (3) “zig-zig”-step
   左→左、またはその逆のとき
                          G


                      P


                  A
148 / 277




   (3) “zig-zig”-step
   左→左、またはその逆のとき
                          G
   2回ではなく3回回転する

                      P


                  A
149 / 277




   (3) “zig-zig”-step
   左→左、またはその逆のとき
                             G
   2回ではなく3回回転する

                   A


                         P
150 / 277




   (3) “zig-zig”-step
   左→左、またはその逆のとき
                         A
   2回ではなく3回回転する

                             G


                         P
151 / 277




   (3) “zig-zig”-step
   左→左、またはその逆のとき
                         A
   2回ではなく3回回転する

                             P


                                 G

   (ただし、後でこれを2回として扱う)
152 / 277




   Splaying operation
    ◦ 偏った位置にあるときだけ余計に回転する
153 / 277




   Splaying operation
    ◦ 偏った位置にあるときだけ余計に回転する

    ◦ そんなので上手くいくわけないだろ!!
154 / 277




   実は上手くいく
155 / 277




   実は上手くいく

   具体的には: 𝑂(log 𝑁) amortized
156 / 277




   実は上手くいく

   具体的には: 𝑂(log 𝑁) amortized
157 / 277




   ならし計算量 (amortized time complexity)

   N個の一連の操作が𝑂(𝑓(𝑁))で行えるとする
                    𝑓 𝑁
 1つ1つの操作は、本当は𝑂(        )とは限らない
                      𝑁
        𝑓 𝑁
 これを𝑂(     )として扱うのが、ならし計算量
          𝑁
158 / 277




   ならし計算量のイメージ



                  操作1
      本当の計算量
                  操作2
                  操作3
                  操作4
      ならし計算量
                  操作5
159 / 277




   ならし計算量の向き/不向き
160 / 277




   ならし計算量の向き/不向き
   向いているもの
    ◦ 全体での処理効率が重視されるバッチ型の処理
    ◦ 例: プログラミングコンテスト
   向いていないもの
    ◦ リアルタイム性能が重視される処理
    ◦ 例: 信号処理
161 / 277




   ならし計算量と平均計算量
162 / 277




   ならし計算量と平均計算量
    ◦ この2つは別物!!
    ◦ ならし計算量 : 時系列上での平均
    ◦ 平均計算量 : 確率変数上での平均
163 / 277




   ならし計算量と平均計算量
    ◦ この2つは別物!!
    ◦ ならし計算量 : 時系列上での平均
    ◦ 平均計算量 : 確率変数上での平均

    ◦ ならし計算量 : 不確定要素は無い!
164 / 277




   Splayのならし計算量の評価
165 / 277




   Splayのならし計算量の評価

   「ポテンシャル関数」の概念を導入
166 / 277




   Splayのならし計算量の評価

   「ポテンシャル関数」の概念を導入
    ◦ 借金みたいなもの
167 / 277




   ポテンシャル関数を用いた計算量の均し(ならし)
   𝑎 𝑗 = 𝑡 𝑗 + Φ 𝑗+1 − Φj
    ◦ 𝑡 𝑗 : その操作の実際の計算量
    ◦ Φ 𝑗+1 − Φj : ポテンシャルの増加量
    ◦ 𝑎 𝑗 : その操作のならし計算量
168 / 277




   ポテンシャル関数を用いた計算量の均し(ならし)
   𝑎 𝑗 = 𝑡 𝑗 + Φ 𝑗+1 − Φj
    ◦ 𝑡 𝑗 : その操作の実際の計算量
    ◦ Φ 𝑗+1 − Φj : ポテンシャルの増加量
    ◦ 𝑎 𝑗 : その操作のならし計算量
   ポテンシャルの意味
    ◦ より大きい: 木はより偏っている
    ◦ より小さい: 木はより平坦になっている
169 / 277




   ならし計算量の総和をとる
    𝑗 𝑎𝑗 = 𝑗 𝑡 𝑗 + Φ 𝑚 − Φ0
    ◦ 𝑗 𝑡 𝑗 : 実際の計算量の総和
    ◦ Φ 𝑚 − Φ0 : ポテンシャルの総変化量
    ◦ 𝑗 𝑎 𝑗 : ならし計算量の総和
170 / 277




   ならし計算量の総和をとる
    𝑗 𝑎𝑗 = 𝑗 𝑡 𝑗 + Φ 𝑚 − Φ0
    ◦ 𝑗 𝑡 𝑗 : 実際の計算量の総和
    ◦ Φ 𝑚 − Φ0 : ポテンシャルの総変化量
    ◦ 𝑗 𝑎 𝑗 : ならし計算量の総和
   ポテンシャルの総変化量が小さければうまく評価でき
    る
171 / 277




   Splay木のポテンシャル
    ◦ Splay木の各頂点の重さを𝑤(𝑥)とする
      計算量の見積もり方にあわせて自由に決めてよい
    ◦ Splay木の頂点のサイズ s 𝑥 =                   𝑤(𝑦)
                              𝑥の全ての子孫 𝑦
    ◦ Splay木の頂点のランク 𝑟 𝑥 = log 2 𝑠(𝑥)
    ◦ Splay木のポテンシャル Φ =              𝑟(𝑥)
                         全ての頂点 𝑥
172 / 277




   Splay木のポテンシャル: 例
173 / 277




   Splay木のポテンシャル: 例
   重さ 𝑤(𝑥)
                           1
    (今回は全て1とする)


                   1               1


               1       1


                   1           1
174 / 277




   Splay木のポテンシャル: 例
   サイズ 𝑠(𝑥)
                             7
    ◦ 部分木の重さの和


                     5               1


                 1       3


                     1           1
175 / 277




   Splay木のポテンシャル: 例
   ランク 𝑟 𝑥 = log 2 𝑠(𝑥)
                                   2.8



                       2.3                0.0


                 0.0         1.6



                       0.0          0.0
176 / 277




   Splay木のポテンシャル: 例
   ポテンシャル: ランクの総和

          Φ = 2.8 + 2.3 + 1.6 = 6.7
177 / 277




   Splay木のポテンシャルの良い性質
178 / 277




   Splay木のポテンシャルの良い性質 …

   回転の影響を受ける頂点が少ない
    ◦ 解析が簡単になる
179 / 277




   アクセス補題 (Access Lemma)
180 / 277




   アクセス補題 (Access Lemma)

   𝑥 : 木のノード
   𝑡 : 木の根 とするとき

   木をsplayする操作一回にかかる時間(回転の回数)
    は、ならし計算量で
              3𝑟 𝑡 − 3𝑟 𝑥 + 1
   以下である。
181 / 277




   アクセス補題の証明
182 / 277




   アクセス補題の証明

   各回転ステップのならし計算量が
    1. “zig”-stepでは 3𝑟 ′ 𝑥 − 3𝑟 𝑥 + 1 以下
    2. それ以外では 3𝑟 ′ 𝑥 − 3𝑟(𝑥) 以下
   (ただし、𝑟′(𝑥) : 操作後のランク)
   であることを示す。
   そうすると、1のケースに登場する𝑟′(𝑥)は初期の𝑟(𝑡)
    と等しい(木全体のサイズの対数)ので、合計すると
    3𝑟 𝑡 − 3𝑟 𝑥 + 1になる。
183 / 277




   アクセス補題の証明 (1) “zig”-step の場合
   𝑟 𝑋 = log 2 (𝑤 𝑋 + 𝑤 𝐴 + 𝑤 𝐵 )
                                   R

   𝑟 𝑅 = log 2 (𝑤 𝑋 + 𝑤 𝐴 + 𝑤 𝐵 + 𝑤 𝐶 + 𝑤(𝑅))
                              X         C


                          A       B
184 / 277




   アクセス補題の証明 (1) “zig”-step の場合
   𝑟 𝑋 = log 2 (𝑤 𝑋 + 𝑤 𝐴 + 𝑤 𝐵 )X
   𝑟 ′ 𝑋 = log 2 (𝑤 𝑋 + 𝑤 𝐴 + 𝑤 𝐵 + 𝑤 𝐶 + 𝑤 𝑅 )
   𝑟 𝑅 = log 2 (𝑤 𝑋 + 𝑤 𝐴 + 𝑤 𝐵 + 𝑤 𝐶 + 𝑤(𝑅))
   𝑟 ′ 𝑅 = log 2 (𝑤 𝑅 + 𝑤 𝐵 + A 𝐶 ) R
                               𝑤


                                 B       C
185 / 277




   アクセス補題の証明 (1) “zig”-step の場合
   𝑟 𝑋 = log 2 (𝑤 𝑋 + 𝑤 𝐴 + 𝑤 𝐵 )
   𝑟 ′ 𝑋 = log 2 (𝑤 𝑋 + 𝑤 𝐴 + 𝑤 𝐵 + 𝑤 𝐶 + 𝑤 𝑅 )
   𝑟 𝑅 = log 2 (𝑤 𝑋 + 𝑤 𝐴 + 𝑤 𝐵 + 𝑤 𝐶 + 𝑤(𝑅))
   𝑟 ′ 𝑅 = log 2 (𝑤 𝑅 + 𝑤 𝐵 + 𝑤 𝐶 )
186 / 277




   アクセス補題の証明 (1) “zig”-step の場合
   𝑟 𝑋 = log 2 (𝑤 𝑋 + 𝑤 𝐴 + 𝑤 𝐵 )
   𝑟 ′ 𝑋 = log 2 (𝑤 𝑋 + 𝑤 𝐴 + 𝑤 𝐵 + 𝑤 𝐶 + 𝑤 𝑅 )
   𝑟 𝑅 = log 2 (𝑤 𝑋 + 𝑤 𝐴 + 𝑤 𝐵 + 𝑤 𝐶 + 𝑤(𝑅))
   𝑟 ′ 𝑅 = log 2 (𝑤 𝑅 + 𝑤 𝐵 + 𝑤 𝐶 )

   𝑟 𝑋 ≤ 𝑟 ′ 𝑋 , 𝑟 ′ 𝑅 ≤ 𝑟(𝑅)
187 / 277




   アクセス補題の証明 (1) “zig”-step の場合
   𝑟 𝑋 ≤ 𝑟 ′ 𝑋 , 𝑟 ′ 𝑅 ≤ 𝑟(𝑅)
   ならし計算量

        𝑎 = 𝑡 + Φ′ − Φ
        = 1 + 𝑟′ 𝑋 + 𝑟′ 𝑅 − 𝑟 𝑋 − 𝑟 𝑅
              ≤ 1 + 𝑟′ 𝑋 − 𝑟 𝑋
              ≤ 1 + 3𝑟 ′ 𝑋 − 3𝑟 𝑋
188 / 277




   アクセス補題の証明 (2) “zigzig”-step の場合
   𝑟 𝑋 = log 2 (𝑤 𝑋 + 𝑠 𝐴 + 𝑠 𝐵 ) G

                                           D
    𝑟 𝑃 = log 2 (𝑤 𝑋 + 𝑠 𝐴 + 𝑠 𝐵 + 𝑠 𝐶P + 𝑤(𝑃))

    𝑟 𝐺 =                        X     C
    log 2 (𝑤 𝑋 + 𝑠 𝐴 + 𝑠 𝐵 + 𝑠 𝐶 + 𝑤 𝑃 + 𝑠 𝐷 + 𝑤 𝐺 )
                              A     B
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 / 277




   アクセス補題の証明 (2) “zigzig”-step の場合
    𝑟 𝑋 = log 2 (𝑤 𝑋 + 𝑠 𝐴 + 𝑠 𝐵 )
    𝑟′ 𝑋 =
    log 2 (𝑤 𝑋 + 𝑠 𝐴 + 𝑠 𝐵 + 𝑠 𝐶 + 𝑠 𝐷 + 𝑤 𝑃 + 𝑤 𝐺 )
    𝑟 𝑃 = log 2 (𝑤 𝑋 + 𝑠 𝐴 + 𝑠 𝐵 + 𝑠 𝐶 + 𝑤(𝑃))
    𝑟 ′ 𝑃 = log 2 (𝑠 𝐵 + 𝑠 𝐶 + 𝑤 𝑃 + 𝑤 𝐺 )
    𝑟 𝐺 =
    log 2 (𝑤 𝑋 + 𝑠 𝐴 + 𝑠 𝐵 + 𝑠 𝐶 + 𝑤 𝑃 + 𝑠 𝐷 + 𝑤 𝐺 )
    𝑟 ′ 𝐺 = log 2 (𝑠 𝐶 + 𝑠 𝐷 + 𝑤 𝐺 )
191 / 277




   アクセス補題の証明 (2) “zigzig”-step の場合
   𝑟′ 𝑋 = 𝑟 𝐺 , 𝑟′ 𝑋 ≤ 𝑟′ 𝑃 , 𝑟 𝑃 ≤ 𝑟 𝑋
192 / 277




   アクセス補題の証明 (2) “zigzig”-step の場合
   𝑟′ 𝑋 = 𝑟 𝐺 , 𝑟′ 𝑃 ≤ 𝑟′ 𝑋 , 𝑟 𝑋 ≤ 𝑟 𝑃

    𝑎 = 𝑡 + Φ′ − Φ
          = 2 + 𝑟′ 𝑋 + 𝑟′ 𝑃 + 𝑟′ 𝐺 − 𝑟 𝑋 − 𝑟 𝑃
          − 𝑟 𝐺
          ≤ 2 + 𝑟 ′ 𝑋 + 𝑟 ′ 𝐺 − 2𝑟 𝑋
193 / 277




   アクセス補題の証明 (2) “zigzig”-step の場合
   2 + 𝑟 ′ 𝑋 + 𝑟 ′ 𝐺 − 2𝑟 𝑋 ≤ 3𝑟 ′ 𝑋 − 3𝑟 𝑋
   理由: 𝑟 ′ 𝐺 + 𝑟 𝑋 − 2𝑟 ′ 𝑋 ≤ −2 を示したい。
                     𝑠′ 𝐺              𝑠 𝑋
   ところで左辺はlog 2            + log 2          であり、
                     𝑠′ 𝑋             𝑠′ 𝑋
   log 2 𝑥が上に凸で、𝑠 ′ 𝐺 + 𝑠 𝑋 ≤ 𝑠′(𝑋)なのでこの
    値は高々−2
   よって不等式は示された。
194 / 277




   アクセス補題の証明 (3) “zigzag”-step の場合
   𝑟′ 𝑋 = 𝑟 𝐺 , 𝑟 𝑋 ≤ 𝑟 𝑃
   𝑠′ 𝑃 + 𝑠′ 𝐺 ≤ 𝑠′ 𝑋
              G
                                   X
          P       D

                           P               G
      A       X
                       A       B       C       D
          B       C
195 / 277




   アクセス補題の証明 (3) “zigzag”-step の場合
   以下(2)と同様
196 / 277




   以上より、Splay操作がならし計算量で𝑂(log 𝑁)であ
    ることがわかった。
   ところで、Splay操作のポテンシャルは高々
    𝑂(𝑁 log 𝑁 )なので、全体で𝑂((𝑄 + 𝑁) log 𝑁)でクエリ
    を処理できることがわかった。
197 / 277




   以上より、Splay操作がならし計算量で𝑂(log 𝑁)であ
    ることがわかった。
   ところで、Splay操作のポテンシャルは高々
    𝑂(𝑁 log 𝑁 )なので、全体で𝑂((𝑄 + 𝑁) log 𝑁)でクエリ
    を処理できることがわかった。

   以上、満点解法その1
198 / 277




   満点解法その2 - Link/Cut木
199 / 277




   満点解法その2 - Link/Cut木

   Link/Cut木
    ◦ 元々、フローアルゴリズムの高速化のためにSleatorとTarjan
      が考案したもの
200 / 277




   満点解法その2 - Link/Cut木

   Link/Cut木
    ◦ 元々、フローアルゴリズムの高速化のためにSleatorとTarjan
      が考案したもの
    ◦ この問題のために必要な実装は、それよりもはるかに容易
201 / 277




   満点解法その2 - Link/Cut木

   Link/Cut木
    ◦ 元々、フローアルゴリズムの高速化のためにSleatorとTarjan
      が考案したもの
    ◦ この問題のために必要な実装は、それよりもはるかに容易
      →Link/Cut木の練習としても適している
202 / 277




   満点解法その2 - Link/Cut木

   Link/Cut木
    ◦ 元々、フローアルゴリズムの高速化のためにSleatorとTarjan
      が考案したもの
    ◦ この問題のために必要な実装は、それよりもはるかに容易
      →Link/Cut木の練習としても適している
    ◦ いろいろなバージョンがあるが、Splay木によるものが使いや
      すい
203 / 277




   予備知識 – Heavy/Light decomposition
204 / 277




   予備知識 – Heavy/Light decomposition
    ◦ 木をパスに分割する方法
                         A


                 B           C


             D       E           F
205 / 277




   予備知識 – Heavy/Light decomposition
    ◦ 木をパスに分割する方法
                         A


                 B           C


             D       E           F
206 / 277




   予備知識 – Heavy/Light decomposition
    ◦ 木をパスに分割する方法

   変な形の木でも、「パスの木」の形に潰すと安定する
207 / 277




   Splay Treeの世界




        列データ           Splay Tree

                    列の畳み込みを効率よく計算
208 / 277




   Splay Treeの世界




        列データ           Splay Tree

                    列の畳み込みを効率よく計算
209 / 277




   Heavy/Light decompositionの世界

         有向木




         列データ                      Splay Tree

     有向木を分解したもの              列の畳み込みを効率よく計算
210 / 277




   Link/Cut Treeの世界

         有向木              Link/Cut Tree

                       パスの畳み込みを効率よく計算




        列データ               Splay Tree

     有向木を分解したもの        列の畳み込みを効率よく計算
211 / 277




   Link/Cut Treeの世界

   H/L分解 = パスからなる木
212 / 277




   Link/Cut Treeの世界

   H/L分解 = パスからなる木
   Link/Cut Tree = Splay木からなる木
213 / 277




   Link/Cut Tree の辺は二種類ある
    ◦ Solid(Heavy) edge
    ◦ Dashed(Light) edge
214 / 277




   Link/Cut Tree の辺は二種類ある

               Solid(Heavy)   Dashed(Light)

     所属        Splay Tree     H/L分解の木

     分類        二分木            多分木

     左右の区別     左右の区別あり        なし

     親         本当は祖先か子孫       本当の親

     子供        本当は祖先か子孫       本当は子孫
215 / 277




   Solid, Dashedの区別
216 / 277




   Solid, Dashedの区別

   いずれも、親方向リンクを持つ


                               X



                       L               R
                           M
217 / 277




   Solid, Dashedの区別

   いずれも、親方向リンクを持つ
   親から左方向リンクがあれば、Solid
                               X



                       L               R
                           M
218 / 277




   Solid, Dashedの区別

   いずれも、親方向リンクを持つ
   親から左方向リンクがあれば、Solid
   親から右方向リンクがあれば、Solid
                               X



                       L               R
                           M
219 / 277




   Solid, Dashedの区別

   いずれも、親方向リンクを持つ
   親から左方向リンクがあれば、Solid
   親から右方向リンクがあれば、Solid
                               X
   どちらもなければ、Dashed


                       L               R
                           M
220 / 277




   Solid, Dashedの区別

   いずれも、親方向リンクを持つ
   親から左方向リンクがあれば、Solid
   親から右方向リンクがあれば、Solid
   どちらもなければ、Dashed

   「右, 左, 親」の3つのリンクだけで構造を保持できる!
221 / 277




   小さな例               A


                   B


               C       F


           D       E
222 / 277




   小さな例               A


                   B


               C       F


           D       E
223 / 277




       小さな例
                F   B   A
            A

        B
                    D   C

    C       F

D       E
                        E
224 / 277




       小さな例            B
            A

        B
                    F           A

    C       F

D       E
                        D

F       B       A
                            C
        D       C

                E
                        E
225 / 277




   Link/Cut Treeの操作: splayLC()

   Link/Cut Tree上では、任意の頂点Xを根に持っていく
    ことができる
    ◦ 元の木の構造は変化しないことに注意
226 / 277




   前準備: splay

   各Splay Tree上でsplayをすることで、Xから今の根ま
    でを点線だけで行けるようにする
227 / 277




   前準備: splay     B

   各Splay Tree上でsplayをすることで、Xから今の根ま
                F          A
    でを点線だけで行けるようにする

                  D

                       C


                   E
228 / 277




   前準備: splay       B

   各Splay Tree上でsplayをすることで、Xから今の根ま
                F          A
    でを点線だけで行けるようにする

                         C

                 D


                     E
229 / 277




   前準備: splay       B

   各Splay Tree上でsplayをすることで、Xから今の根ま
                F          A
    でを点線だけで行けるようにする

                         C   EからBまで、点
                             線のみで行ける
                 D             ようになる


                     E
230 / 277




   splayLC() のメイン操作: つなぎ変え(expose操作)

   パスのつなぎ変え操作を行う

   元の木ではこんな感じ
231 / 277




                       A
    splayLC() のメイン操作: つなぎ変え(expose操作)

             B
    パスのつなぎ変え操作を行う

   元の木ではこんな感じ
            C          F


             D     E
232 / 277




                       A
    splayLC() のメイン操作: つなぎ変え(expose操作)

             B
    パスのつなぎ変え操作を行う

   元の木ではこんな感じ
            C          F


             D     E
233 / 277




                       A
    splayLC() のメイン操作: つなぎ変え(expose操作)

             B
    パスのつなぎ変え操作を行う

   元の木ではこんな感じ
            C          F


             D     E
234 / 277




   splayLC() のメイン操作: つなぎ変え(expose操作)

   パスのつなぎ変え操作を行う

   Link/Cut 木でも、左向きのSolid辺を付け替えるだけ
235 / 277




   splayLC() のメイン操作: B
                      つなぎ変え(expose操作)

          F
    パスのつなぎ変え操作を行う         A

   Link/Cut 木でも、左向きのSolid辺を付け替えるだけ
                     C

                D


                    E
236 / 277




   splayLC() のメイン操作: B
                      つなぎ変え(expose操作)

          F
    パスのつなぎ変え操作を行う         A

   Link/Cut 木でも、左向きのSolid辺を付け替えるだけ
                     C

                D


                    E
237 / 277




                       B
   splayLC() のメイン操作: つなぎ変え(expose操作)

            C
    パスのつなぎ変え操作を行う          A

             E
    Link/Cut 木でも、左向きのSolid辺を付け替えるだけ




             D             F
238 / 277




   左向きの辺をつなぎ替えるだけで、Eが一番上の木に
    所属するようになった
239 / 277




   左向きの辺をつなぎ替えるだけで、Eが一番上の木に
    所属するようになった

   最後にもう1度splay()操作を行うことで、Link/Cut
    Treeの一番上の根にEが来る
240 / 277




   L/C木のsplayLC()はSplay Treeの解析を少し応用す
    ると、対数時間であることが言える
241 / 277




   L/C木のsplayLC()はSplay Treeの解析を少し応用す
    ると、対数時間であることが言える

   1回ごとのsplay()操作が対数時間であることは既に
    わかっている
242 / 277




   L/C木のsplayLC()はSplay Treeの解析を少し応用す
    ると、対数時間であることが言える

   1回ごとのsplay()操作が対数時間であることは既に
    わかっている
   しかし実際にはsplay()操作が𝑘回呼ばれている
    ◦ 𝑘は、パス分割された木の上での深さ
243 / 277




   ポテンシャルの定義
    ◦ サイズ = solid/dashedに関わらず、子孫になっている頂点の
      数
    ◦ ランク = その対数
    ◦ ポテンシャル = ランクの総和の2倍
      として定める
244 / 277




   Splay Treeのならし計算量は 1 + 3𝑟 𝑡 − 3𝑟(𝑥) だっ
    た
   今回のならし計算量は𝑘 + 6𝑟 𝑡 − 6𝑟(𝑥)になる
    ◦ 「Splayが𝑘回呼ばれる」という認識を改めてみる
    ◦ Splayは根に向かって順番に呼ばれるということを考慮すると、
      「Splayが1回呼ばれるが、途中でk回、強制的にzigステップを
      使われるかもしれない」と考えることができる
    ◦ 係数が2倍なのはポテンシャルの定義を変えたから
245 / 277




   余った定数項𝑘の回収

   Expose操作のあとに1回行うsplay操作: k回の回転を
    行う。
   ポテンシャルの定義を2倍にしたので、splayの回転操
    作1回につき1の追加コストを課しても問題ない
246 / 277




   ならしコスト6 log 2 𝑁のsplay操作を2回呼んでいるの
    で、splayLC()のならし計算量は12 log 2 𝑁 = 𝑂(log 𝑁)
    であるとわかった。
247 / 277




   AとBのLCAを求める。
248 / 277




   AとBのLCAを求めるには、まず
    1. Bに対してsplayLC()を行う
    2. Aに対してsplayLC()を行う
   このとき、Bは浅い位置にいる。
    ◦ Splay Treeに対するSplay操作1回で、他の頂点の深さは高々
      2段しか下がらないので、この時点でBは深さ高々4程度。
249 / 277




   AとBの位置関係に基いて条件分岐
250 / 277




   AとBの位置関係に基いて条件分岐
   (1) BがAの左側にある場合
    ◦ この場合は、BはAの子孫ということになるので、AとBのLCA
      はAになる。
   (2) BがAの右側にある場合
    ◦ 次のページへ
251 / 277




   BがAの右側にある場合の条件分岐
   (1) BがAと同じSplay Treeに属する場合
    ◦ この場合は、AはBの子孫ということになるので、AとBのLCA
      はBになる。
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 / 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 / 277




   クエリ1,2番に対応する「接続」「切断」は、
    Link/Cut Treeの”link”, “cut” に対応する。
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 / 277




   クエリ1,2番に対応する「接続」「切断」は、
    Link/Cut Treeの”link”, “cut” に対応する。
   (2) Cut操作 – Aを親から切り離す
    ◦ AをsplayLC()してからAの右の子を切り離す。
    ◦ 計算量:ポテンシャルは明らかに減っている。
257 / 277




   以上がLink/Cut Treeによる満点解法。
258 / 277




   Euler Tour Tree と Link/Cut Tree は動的木の筆頭
259 / 277




   Euler Tour Tree と Link/Cut Tree は動的木の筆頭
   今回はどちらを選ぶべきだったか?
260 / 277




   Euler Tour Tree と Link/Cut Tree は動的木の筆頭
   今回はどちらを選ぶべきだったか?

   (他の問題は解き終わっているとして)
261 / 277




   Euler Tour Tree
    ◦ 知識:
    ◦ 実装:



   Link/Cut Tree
    ◦ 知識:
    ◦ 実装:
262 / 277




   Euler Tour Tree
    ◦ 知識: 過去にも出題済みの知識の組合せ。
    ◦ 実装:



   Link/Cut Tree
    ◦ 知識:
    ◦ 実装:
263 / 277




   Euler Tour Tree
    ◦ 知識: 過去にも出題済みの知識の組合せ。
    ◦ 実装: 組み合わせてはいけないものを組み合わせてしまった
      感じ


   Link/Cut Tree
    ◦ 知識:
    ◦ 実装:
264 / 277




   Euler Tour Tree
    ◦ 知識: 過去にも出題済みの知識の組合せ。
    ◦ 実装: 組み合わせてはいけないものを組み合わせてしまった
      感じ


   Link/Cut Tree
    ◦ 知識: 必須
    ◦ 実装:
265 / 277




   Euler Tour Tree
    ◦ 知識: 過去にも出題済みの知識の組合せ。
    ◦ 実装: 組み合わせてはいけないものを組み合わせてしまった
      感じ


   Link/Cut Tree
    ◦ 知識: 必須
    ◦ 実装: 頂点にデータを持たせなくてよいなど、この問題におい
      ては極めて有利
266 / 277




   Euler Tour Tree
    ◦ 知識: 過去にも出題済みの知識の組合せ。
    ◦ 実装: 組み合わせてはいけないものを組み合わせてしまった
      感じ

   Link/Cut Tree
    ◦ 知識: 必須
    ◦ 実装: 頂点にデータを持たせなくてよいなど、この問題におい
      ては極めて有利
   知っているならLink/Cut を書くべきだったかもしれな
    い
267 / 277




   Link/Cutを学ぶべきか?
268 / 277




   Link/Cutを学ぶべきか?
    ◦ Link/Cutでなければ出来ない、という問題は、恐らくない
269 / 277




   Link/Cutを学ぶべきか?
    ◦ Link/Cutでなければ出来ない、という問題は、恐らくない

    ◦ しかし、Link/Cutを使うと有利な問題は実際に存在している
270 / 277




   qnighyからの提案
271 / 277




   qnighyからの提案
    ◦ 合宿参加者の大半にとっては、Link/Cut Treeを習得するコ
      ストが高くつく上に、他の学習をしたほうがずっと為になると
      思う。
272 / 277




   qnighyからの提案
    ◦ 合宿参加者の大半にとっては、Link/Cut Treeを習得するコ
      ストが高くつく上に、他の学習をしたほうがずっと為になると
      思う。
    ◦ より上位の人や、単純に興味があるという人に関しては、こ
      の限りではない。
273 / 277




   qnighyからの提案
    ◦ 合宿参加者の大半にとっては、Link/Cut Treeを習得するコ
      ストが高くつく上に、他の学習をしたほうがずっと為になると
      思う。
    ◦ より上位の人や、単純に興味があるという人に関しては、こ
      の限りではない。
    ◦ いずれにせよ、学習するつもりなら、身に付けるために問題
      を解くべきだろう。
274 / 277




   JOI2010春合宿 Day4 “Highway”
   JOI2012本選 問題5 “Festivals in JOI Kingdom”
   IOI2011 Day2 “Elephants”
   IJPC2012 Day3 “Animals2”
275 / 277




   完全制覇・ツリー上でのクエリ処理技法 [iwiwi]
    http://topcoder.g.hatena.ne.jp/iwiwi/20111205/13
    23099376
   プログラミングコンテストでのデータ構造 2 ~動的木
    編~ [iwiwi]
    http://www.slideshare.net/iwiwi/2-12188845
   蟻本 [iwiwi]
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




12

10

8

6

4

2

0
     0   10   20   30   40   50   60   70   80   90     100

Más contenido relacionado

La actualidad más candente

AtCoder Regular Contest 039 解説
AtCoder Regular Contest 039 解説AtCoder Regular Contest 039 解説
AtCoder Regular Contest 039 解説AtCoder Inc.
 
Re永続データ構造が分からない人のためのスライド
Re永続データ構造が分からない人のためのスライドRe永続データ構造が分からない人のためのスライド
Re永続データ構造が分からない人のためのスライドMasaki Hara
 
実践・最強最速のアルゴリズム勉強会 第五回講義資料(ワークスアプリケーションズ & AtCoder)
実践・最強最速のアルゴリズム勉強会 第五回講義資料(ワークスアプリケーションズ & AtCoder)実践・最強最速のアルゴリズム勉強会 第五回講義資料(ワークスアプリケーションズ & AtCoder)
実践・最強最速のアルゴリズム勉強会 第五回講義資料(ワークスアプリケーションズ & AtCoder)AtCoder Inc.
 
LCA and RMQ ~簡潔もあるよ!~
LCA and RMQ ~簡潔もあるよ!~LCA and RMQ ~簡潔もあるよ!~
LCA and RMQ ~簡潔もあるよ!~Yuma Inoue
 
区間分割の仕方を最適化する動的計画法 (JOI 2021 夏季セミナー)
区間分割の仕方を最適化する動的計画法 (JOI 2021 夏季セミナー)区間分割の仕方を最適化する動的計画法 (JOI 2021 夏季セミナー)
区間分割の仕方を最適化する動的計画法 (JOI 2021 夏季セミナー)Kensuke Otsuki
 
Amortize analysis of Deque with 2 Stack
Amortize analysis of Deque with 2 StackAmortize analysis of Deque with 2 Stack
Amortize analysis of Deque with 2 StackKen Ogura
 
直前合宿 講義スライド
直前合宿 講義スライド直前合宿 講義スライド
直前合宿 講義スライドtozan gezan
 
指数時間アルゴリズム入門
指数時間アルゴリズム入門指数時間アルゴリズム入門
指数時間アルゴリズム入門Yoichi Iwata
 
Union find(素集合データ構造)
Union find(素集合データ構造)Union find(素集合データ構造)
Union find(素集合データ構造)AtCoder Inc.
 
AtCoder Regular Contest 045 解説
AtCoder Regular Contest 045 解説AtCoder Regular Contest 045 解説
AtCoder Regular Contest 045 解説AtCoder Inc.
 
AtCoder Regular Contest 048
AtCoder Regular Contest 048AtCoder Regular Contest 048
AtCoder Regular Contest 048AtCoder Inc.
 

La actualidad más candente (20)

Arc041
Arc041Arc041
Arc041
 
グラフネットワーク〜フロー&カット〜
グラフネットワーク〜フロー&カット〜グラフネットワーク〜フロー&カット〜
グラフネットワーク〜フロー&カット〜
 
AtCoder Regular Contest 039 解説
AtCoder Regular Contest 039 解説AtCoder Regular Contest 039 解説
AtCoder Regular Contest 039 解説
 
Re永続データ構造が分からない人のためのスライド
Re永続データ構造が分からない人のためのスライドRe永続データ構造が分からない人のためのスライド
Re永続データ構造が分からない人のためのスライド
 
実践・最強最速のアルゴリズム勉強会 第五回講義資料(ワークスアプリケーションズ & AtCoder)
実践・最強最速のアルゴリズム勉強会 第五回講義資料(ワークスアプリケーションズ & AtCoder)実践・最強最速のアルゴリズム勉強会 第五回講義資料(ワークスアプリケーションズ & AtCoder)
実践・最強最速のアルゴリズム勉強会 第五回講義資料(ワークスアプリケーションズ & AtCoder)
 
全域木いろいろ
全域木いろいろ全域木いろいろ
全域木いろいろ
 
LCA and RMQ ~簡潔もあるよ!~
LCA and RMQ ~簡潔もあるよ!~LCA and RMQ ~簡潔もあるよ!~
LCA and RMQ ~簡潔もあるよ!~
 
区間分割の仕方を最適化する動的計画法 (JOI 2021 夏季セミナー)
区間分割の仕方を最適化する動的計画法 (JOI 2021 夏季セミナー)区間分割の仕方を最適化する動的計画法 (JOI 2021 夏季セミナー)
区間分割の仕方を最適化する動的計画法 (JOI 2021 夏季セミナー)
 
Amortize analysis of Deque with 2 Stack
Amortize analysis of Deque with 2 StackAmortize analysis of Deque with 2 Stack
Amortize analysis of Deque with 2 Stack
 
動的計画法を極める!
動的計画法を極める!動的計画法を極める!
動的計画法を極める!
 
Binary indexed tree
Binary indexed treeBinary indexed tree
Binary indexed tree
 
直前合宿 講義スライド
直前合宿 講義スライド直前合宿 講義スライド
直前合宿 講義スライド
 
Rolling hash
Rolling hashRolling hash
Rolling hash
 
双対性
双対性双対性
双対性
 
直交領域探索
直交領域探索直交領域探索
直交領域探索
 
指数時間アルゴリズム入門
指数時間アルゴリズム入門指数時間アルゴリズム入門
指数時間アルゴリズム入門
 
Union find(素集合データ構造)
Union find(素集合データ構造)Union find(素集合データ構造)
Union find(素集合データ構造)
 
AtCoder Regular Contest 045 解説
AtCoder Regular Contest 045 解説AtCoder Regular Contest 045 解説
AtCoder Regular Contest 045 解説
 
最大流 (max flow)
最大流 (max flow)最大流 (max flow)
最大流 (max flow)
 
AtCoder Regular Contest 048
AtCoder Regular Contest 048AtCoder Regular Contest 048
AtCoder Regular Contest 048
 

Destacado

“A ::= aAa / a” in PEG
“A ::= aAa / a” in PEG“A ::= aAa / a” in PEG
“A ::= aAa / a” in PEGMasaki Hara
 
Proving Decidability of Intuitionistic Propositional Calculus on Coq
Proving Decidability of Intuitionistic Propositional Calculus on CoqProving Decidability of Intuitionistic Propositional Calculus on Coq
Proving Decidability of Intuitionistic Propositional Calculus on CoqMasaki Hara
 
joi2012-sp-day2-broadcasting
joi2012-sp-day2-broadcastingjoi2012-sp-day2-broadcasting
joi2012-sp-day2-broadcastingMasaki Hara
 
ご静聴ありがとうございました
ご静聴ありがとうございましたご静聴ありがとうございました
ご静聴ありがとうございましたMasaki Hara
 
いろいろな問題の解説
いろいろな問題の解説いろいろな問題の解説
いろいろな問題の解説Masaki Hara
 
永続データ構造が分からない人のためのスライド
永続データ構造が分からない人のためのスライド永続データ構造が分からない人のためのスライド
永続データ構造が分からない人のためのスライドMasaki Hara
 
書くネタがCoqしかない
書くネタがCoqしかない書くネタがCoqしかない
書くネタがCoqしかないMasaki Hara
 

Destacado (9)

“A ::= aAa / a” in PEG
“A ::= aAa / a” in PEG“A ::= aAa / a” in PEG
“A ::= aAa / a” in PEG
 
Proving Decidability of Intuitionistic Propositional Calculus on Coq
Proving Decidability of Intuitionistic Propositional Calculus on CoqProving Decidability of Intuitionistic Propositional Calculus on Coq
Proving Decidability of Intuitionistic Propositional Calculus on Coq
 
joi2012-sp-day2-broadcasting
joi2012-sp-day2-broadcastingjoi2012-sp-day2-broadcasting
joi2012-sp-day2-broadcasting
 
ご静聴ありがとうございました
ご静聴ありがとうございましたご静聴ありがとうございました
ご静聴ありがとうございました
 
いろいろな問題の解説
いろいろな問題の解説いろいろな問題の解説
いろいろな問題の解説
 
Coqの公理
Coqの公理Coqの公理
Coqの公理
 
永続データ構造が分からない人のためのスライド
永続データ構造が分からない人のためのスライド永続データ構造が分からない人のためのスライド
永続データ構造が分からない人のためのスライド
 
Coqでsprintf
CoqでsprintfCoqでsprintf
Coqでsprintf
 
書くネタがCoqしかない
書くネタがCoqしかない書くネタがCoqしかない
書くネタがCoqしかない
 

Spaceships 解説

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