SlideShare a Scribd company logo
1 of 30
Download to read offline
2012/3/20 NTTデータ駒場研修所 (情報オリンピック春合宿)




   プログラミングコンテストでの
             データ構造2
                 ~動的木編~

            東京大学情報理工学系研究科

                   秋葉 拓哉
                                      1
動的木
• 実は動的木にもいくつかある
 – 「順位キュー」的な言葉       (⇔ 二分ヒープ, フィボナッチヒープ)




• ポピュラーな動的木
 – Link-Cut 木
 – Euler-Tour 木 (動的グラフで内部的に使う)


• 今日は Link-Cut 木 の話をします

                                            2
Link-Cut 木
• 木を処理する神がかり的なデータ構造!!
 (木で木を処理するのでややこしい…)


• 以下が 𝑂(log 𝑛) 時間でできる.
 – 頂点の親を変更 (link) / 削除 (cut)
 – 木の根を求める (root) / 木の根を変更 (evert)
 – パスに対する頂点・枝の値のクエリ
  (sum・max・更新など)

                                     3
Link-Cut 木は現実
                   そんなのどうせ実装できっこない…
  (´・_・`)


                    IOI は Link-Cut 木で常勝!!
 Fan Haoqiang 氏
                               ※発言はフィクションです
      (中国)


Fan Haoqiang 氏は IOI’11 の Elephants で Link-Cut 木を実装!
• これに関して特別賞を受賞
• 599 点で準優勝

                                                      4
…でもやっぱその前に!
• 動的木は本当に必要?いつものじゃダメ?


• やはり,実装が面倒,避けられたら避けたい
• 実際のとこ,本当に必要になる問題は皆無


(特別賞を狙いたいのであればこの限りではない)




                          5
例
            木上の距離クエリ
    • 2 頂点間の枝を作成・削除してください
    • 2 頂点間の距離を答えてください
    ただしグラフは常に森.


           ツリーを処理するデータ構造なんて他に知らない…
               動的木じゃないとできっこないよ…
(´・_・`)

             平方分割でもできるよ (重要!!)
( ・`д・´)

                                     6
クエリを平方分割
クエリ          • クエリを 𝐵 個ごとのブロックに分割

      終わった
             • 各ブロック内で操作に関わる頂点は
       部分      高々2𝐵個
             • それ以外の頂点は興味が無いので,
      今やる
       部分      ブロックを処理する最初に,縮約
              – 𝑂(𝐵) 頂点の森になる




                                  7
クエリを平方分割
      クエリ            縮約
                                        • すると各クエリは 𝑂(𝐵) で処理可
                   ←
        𝑂(𝐵)         𝑂(𝑁)                      – 普通に 𝑂(𝐵) 頂点の木を探索するだけ
           …




                        縮約
                   ←                             𝑄
                        𝑂(𝑁)
        𝑂(𝐵)                              𝑂           𝑁 + 𝑄𝐵 = 𝑂 𝑄                                𝑁 時間
                                                 𝐵
           …




                                                                                            ↑
                        縮約                                                        𝐵=        𝑁 とした
                   ←
        𝑂(𝐵)            𝑂(𝑁)
           …




                                        ただし,クエリが先読みできないと無理


類似した問題と,より詳しい解説:
http://acm-icpc.aitea.net/index.php?plugin=attach&refer=2010%2FPractice%2F%B2%C6%B9%E7%BD%C9%2F%B9%D6%C9%BE&openfile=2d.pdf

                                                                                                                              8
レベル別 Link-Cut 木
オプション
          link, cut,     evert,   辺質問・更新
          頂点質問           頂点更新     (実装そこそこ)
         (実装一瞬)          (実装少し)


ベース                     expose
                       (実装そこそこ)


• オプションは独立に選んで実装可

• 「頂点質問」 = ある頂点から根までのパスにおける頂点の属
  性の sum とか max とかのこと
• 「頂点更新」 =とはパス上の頂点全部に x 足すとかのこと

                                             9
基本アイディア
• ツリーをパスの集合みたいに表現
• パスを平衡二分探索木で管理




                    10
基本アイディア
パスへの分解は決まってない + 固定じゃない




 こうなってるかもしれないし   こうなってるかも
                            11
核となる操作 expose(𝒗)
    頂点 v から根へのパスを繋げる



                                ←切れる

v                           v
                    切
                    れ



                        ↑
                    る




    平衡二分探索木の split / merge を使う
                                       12
link, cut の雰囲気
• cut(𝑣): 𝑣 から親への辺を削除
• link(𝑣, 𝑤): 𝑣 の親を 𝑤 にする
      平衡二分探索木を切ったり繋げたりするだけ



          w                 w
                    cut
              v                 v
                    link




                                    13
頂点クエリ
• sumv(𝑣): 頂点 v から根までの頂点たちに書いて
  ある数の和
 (あるいは minv, maxv, …)


やり方
• 平衡二分探索木に,部分木の和を持たせる
• expose(𝑣) して,和を見るだけ


                             14
各操作の計算量
結論: スプレー木を用いるとならし 𝑂 log 𝑛 時間

𝑂 log 2 𝑛 時間の略証:
• expose の計算量だけ考えれば良い (他は余裕)
• 平衡二分探索木で管理されるパスに入る・出る枝の本数
  をならし 𝑂 log 𝑛 本に抑えられれば良い


                        1 本 “入って”
     v             v    2 本 “出た”


                                    15
• 出るためには入る必要がある,入る回数を抑えれば OK
• 元の木の Heavy-Light Decomposition を考える
• Light-Edge の本数を抑える
  – 各頂点から根までの Light Edge はそもそも 𝑂 log 𝑛 本
  – よって,入る Light-Edgeは 𝑂 log 𝑛 本
• Heavy-Edge の本数を抑える
  – 1 度にいじる Heavy-Edge の本数は多いかも,でも,
  – Heavy-Edge が入るということは Light-Edge が出る
  – Light-Edge が出るためには Light-Edge が入ってるはず
  – それはさっき数えた! 各クエリ 𝑂 log 𝑛 本!
  – よってならし 𝑂 log 𝑛 本になる
• よって 𝑂 log 𝑛 ならし本.よって 𝑂 log 2 𝑛 ならし時間.

                                            16
各操作の計算量
𝑂 log 𝑛 時間:
• スプレー木のポテンシャルに踏み入って解析する
• 今日は省略


     Link-Cut 木を実装していこう!
              (気合い!)
     (といってもスプレー木が出来れば殆ど終わり)




                              17
実装:ノードの構造体
struct node_t {
 node_t *pp, *lp, *rp; // 親,左の子,右の子

// このノードは木の根?
bool is_root() {
  return !pp || (pp->lp != this && pp->rp != this);
}
…


Is_root は何故 !pp だけじゃない?
→ pp をパスの親を表すのにも使うため (後述)
 (こうすると実装が凄い楽になります)
親でありながら子でないことがある

                                                      18
実装:ノードの構造体 (続き)
void rotr() { // 右回転                                   void splay() { // スプレー操作
  node_t *q = pp, *r = q->pp;                            while (!is_root()) {
  if ((q->lp = rp)) rp->pp = q;                            node_t *q = pp;
  rp = q; q->pp = this;                                    if (q->is_root()) {
  if ((pp = r)) {                                            if (q->lp == this) rotr();
    if (r->lp == q) r->lp = this;                            else rotl();
    if (r->rp == q) r->rp = this;                          } else {
  }                                                          node_t *r = q->pp;
}                                                            if (r->lp == q) {
                                                               if (q->lp == this) { q->rotr(); rotr(); }
void rotl() { // 左回転                                           else { rotl(); rotr(); }
  node_t *q = pp, *r = q->pp;                                } else {
  if ((q->rp = lp)) lp->pp = q;                                if (q->rp == this) { q->rotl(); rotl(); }
  lp = q; q->pp = this;                                        else { rotr(); rotl(); }
  if ((pp = r)) {                                            }
    if (r->lp == q) r->lp = this;                          }
    if (r->rp == q) r->rp = this;                        }
  }                                                    }
}



               スプレー操作を Bottom-Up の方式で実装する
   (普通に平衡二分探索木でスプレー木を使うときは Top-Down の方式の方が良いが,
        今回はノードのポインタを知ってるところから splay したいので Bottom-Up)
           (参考:Top-Down の実装例 http://www.prefield.com/algorithm/container/splay_tree.html)

                                                                                                           19
実装:パスの親                    NULL

                                        3
    1
                                   2              5
        2               表現の例
                               1              4
    a       3

    b           4                       a
                    5                             c
    c
                                              b


• pp (親へのポインタ) を 2 通りの使い方をすると楽
 – 普通に二分探索木内での親へのポインタ(緑・青の両向き)
 – パスからの親へのポインタ (赤色の片方向)


                                                      20
expose(c)          1
    1
        2                                           2

            3                                 a         3
a
b               4                             b                 4
c                   5                                               5
                                              c

    NULL                                     NULL

        2                                     2
1           3                            1                  3
                        5                                           5
                4                                               4

            a                                       a
                    c                                           c
                b                                       b
                                         ノード 2 の右の子を
こうなってたら
                                        3 から a にするだけ!
                                                                        21
実装:expose
やること:                                       node_t *expose(node_t *x) {
                                              node_t *rp = NULL;
1. 今いる頂点を splay                               for (node_t *p = x; p; p = p->pp) {
                                                p->splay();
2. 右側にさっきまで居た木を                                 p->rp = rp;
                                                rp = p;
   くっつける                                      }
                                              x->splay(); // しとくと便利
3. 上の木に進む                                     return x;
                                            }



        3                   3               2                            2
                                                     3
    2           5       2           5   1                           1                     c
                                                             5
1           4       1           4                        4                    a
                                                                                      b
        a                           c                        c
                c           a                    a                                3
                                                                                          5
            b                   b                        b                            4

    さいしょ                Splay(c)        2 に移動,splay(2)             2 の右に c をつける
                                                                              22
実装:link, cut
expose まで出来ていればもう簡単

void cut(node_t *c) {
  expose(c);                        cut                         p
  node_t *p = c->lp;                •   c を expose                         c
  c->lp = NULL;
  p->pp = NULL;                     •   c の左を切断
}




                                                                        link
                                                          cut
void link(node_t *c, node_t *p) {
  expose(c);                        link
  expose(p);                        •     c, p を expose             p
  c->pp = p;                        •     p の右に c を                       c
  p->rp = c;                              つける
}

                                                                               23
実装:evert
evert(𝑣):𝑣 を根にする

木のパスの向きを反転すればよい

                   v
                       void evert(node_t *p) {
                         node_t *r = expose(p);
                         r->rev = true;
    v                  }

                            +
                         スプレー木に
                        反転の機能を実装

                                              24
実装:辺属性
• 木の辺に情報をつける
• 回転とか張替えでポインタと一緒に情報を保つ (注意深く)
• 部分木に関する情報も保つ
                         NULL


                        2 3          3
     1 1
                     1 2             4 5
        2 2
      5              1   5       4
    a      3 3
  6                          a
    b        4   4               6
  7              5                       c
    c
                                 b 7


                                             25
応用:Elephants (IOI’11)
• 象が 𝑁 匹並んでます

• クエリが大量にくる
 – Update(𝑖, 𝑥)
 – i 匹目の象を場所 x に移動


• クエリの度に答える
 – 何台のカメラで全員写る?
 – カメラ:幅 𝐿




                             26
応用:Elephants (IOI’11)
• 愚直な解法:クエリ毎に計算する
 – 貪欲法の典型的問題
 – 一番左の象を覆う,を繰り返せば良い


• 動的木を使う解法:
 – 似たような感じのことを木で表現する
 – 移動は木のちょっとした更新になる
 – よってクエリに爆速で答えられる

                          27
応用:Elephants (IOI’11)



• 象の場所に ● を書く
• そこから L 先に ○ を書き,●から辺を張る
• ○からはすぐ次の●か○に辺を張る

• これはツリー!
• 一番左から辿って,●の個数が答え!

                            28
Link-Cut 木まとめ
• まずはもっと容易な道具を検討!
 – クエリの平方分割


• 実装しよう (下に行くほど大変)
 – expose, link, cut, root, 頂点の情報に関する質問
 – evert, 頂点の情報の更新
 – 辺の情報に関する質問・更新



                                          29
全体まとめと私見
話したこと
•   平衡二分探索木
    – 本当に必要か検討,必要な場所だけ作るセグメント木
    – Treapのアイディア,楽な実装法の議論,応用例
    – その他の平衡二分探索木の紹介
•   動的木
    – 本当に必要か検討,クエリの平方分割
    – Link-Cut Tree のアイディア,楽な実装法の議論,応用例
私見
•   これらは難易度が高く,想定解法としての出題頻度は低い
•   よって,習得の優先度は高くない
•   ただし,非常に強力な道具なので,武器にできれば得をするかも?


                                          30

More Related Content

What's hot

様々な全域木問題
様々な全域木問題様々な全域木問題
様々な全域木問題tmaehara
 
ウェーブレット木の世界
ウェーブレット木の世界ウェーブレット木の世界
ウェーブレット木の世界Preferred Networks
 
LCA and RMQ ~簡潔もあるよ!~
LCA and RMQ ~簡潔もあるよ!~LCA and RMQ ~簡潔もあるよ!~
LCA and RMQ ~簡潔もあるよ!~Yuma Inoue
 
Re永続データ構造が分からない人のためのスライド
Re永続データ構造が分からない人のためのスライドRe永続データ構造が分からない人のためのスライド
Re永続データ構造が分からない人のためのスライドMasaki Hara
 
ユークリッド最小全域木
ユークリッド最小全域木ユークリッド最小全域木
ユークリッド最小全域木理玖 川崎
 
二部グラフの最小点被覆と最大安定集合と最小辺被覆の求め方
二部グラフの最小点被覆と最大安定集合と最小辺被覆の求め方二部グラフの最小点被覆と最大安定集合と最小辺被覆の求め方
二部グラフの最小点被覆と最大安定集合と最小辺被覆の求め方Kensuke Otsuki
 
図と実装で理解する『木構造入門』
図と実装で理解する『木構造入門』図と実装で理解する『木構造入門』
図と実装で理解する『木構造入門』Proktmr
 
Rolling Hashを殺す話
Rolling Hashを殺す話Rolling Hashを殺す話
Rolling Hashを殺す話Nagisa Eto
 
深さ優先探索による塗りつぶし
深さ優先探索による塗りつぶし深さ優先探索による塗りつぶし
深さ優先探索による塗りつぶしAtCoder Inc.
 
直前合宿 講義スライド
直前合宿 講義スライド直前合宿 講義スライド
直前合宿 講義スライドtozan gezan
 

What's hot (20)

直交領域探索
直交領域探索直交領域探索
直交領域探索
 
様々な全域木問題
様々な全域木問題様々な全域木問題
様々な全域木問題
 
Convex Hull Trick
Convex Hull TrickConvex Hull Trick
Convex Hull Trick
 
ウェーブレット木の世界
ウェーブレット木の世界ウェーブレット木の世界
ウェーブレット木の世界
 
LCA and RMQ ~簡潔もあるよ!~
LCA and RMQ ~簡潔もあるよ!~LCA and RMQ ~簡潔もあるよ!~
LCA and RMQ ~簡潔もあるよ!~
 
目指せグラフマスター
目指せグラフマスター目指せグラフマスター
目指せグラフマスター
 
最大流 (max flow)
最大流 (max flow)最大流 (max flow)
最大流 (max flow)
 
Binary indexed tree
Binary indexed treeBinary indexed tree
Binary indexed tree
 
Nazoki
NazokiNazoki
Nazoki
 
Re永続データ構造が分からない人のためのスライド
Re永続データ構造が分からない人のためのスライドRe永続データ構造が分からない人のためのスライド
Re永続データ構造が分からない人のためのスライド
 
ユークリッド最小全域木
ユークリッド最小全域木ユークリッド最小全域木
ユークリッド最小全域木
 
グラフネットワーク〜フロー&カット〜
グラフネットワーク〜フロー&カット〜グラフネットワーク〜フロー&カット〜
グラフネットワーク〜フロー&カット〜
 
全域木いろいろ
全域木いろいろ全域木いろいろ
全域木いろいろ
 
二部グラフの最小点被覆と最大安定集合と最小辺被覆の求め方
二部グラフの最小点被覆と最大安定集合と最小辺被覆の求め方二部グラフの最小点被覆と最大安定集合と最小辺被覆の求め方
二部グラフの最小点被覆と最大安定集合と最小辺被覆の求め方
 
図と実装で理解する『木構造入門』
図と実装で理解する『木構造入門』図と実装で理解する『木構造入門』
図と実装で理解する『木構造入門』
 
Rolling Hashを殺す話
Rolling Hashを殺す話Rolling Hashを殺す話
Rolling Hashを殺す話
 
深さ優先探索による塗りつぶし
深さ優先探索による塗りつぶし深さ優先探索による塗りつぶし
深さ優先探索による塗りつぶし
 
Chokudai search
Chokudai searchChokudai search
Chokudai search
 
線形計画法入門
線形計画法入門線形計画法入門
線形計画法入門
 
直前合宿 講義スライド
直前合宿 講義スライド直前合宿 講義スライド
直前合宿 講義スライド
 

Viewers also liked

CVPR2016読み会 Sparsifying Neural Network Connections for Face Recognition
CVPR2016読み会 Sparsifying Neural Network Connections for Face RecognitionCVPR2016読み会 Sparsifying Neural Network Connections for Face Recognition
CVPR2016読み会 Sparsifying Neural Network Connections for Face RecognitionKoichi Takahashi
 
20170819 CV勉強会 CVPR 2017
20170819 CV勉強会 CVPR 201720170819 CV勉強会 CVPR 2017
20170819 CV勉強会 CVPR 2017issaymk2
 
On the Dynamics of Machine Learning Algorithms and Behavioral Game Theory
On the Dynamics of Machine Learning Algorithms and Behavioral Game TheoryOn the Dynamics of Machine Learning Algorithms and Behavioral Game Theory
On the Dynamics of Machine Learning Algorithms and Behavioral Game TheoryRikiya Takahashi
 
Stochastic Variational Inference
Stochastic Variational InferenceStochastic Variational Inference
Stochastic Variational InferenceKaede Hayashi
 
Greed is Good: 劣モジュラ関数最大化とその発展
Greed is Good: 劣モジュラ関数最大化とその発展Greed is Good: 劣モジュラ関数最大化とその発展
Greed is Good: 劣モジュラ関数最大化とその発展Yuichi Yoshida
 
sublabel accurate convex relaxation of vectorial multilabel energies
sublabel accurate convex relaxation of vectorial multilabel energiessublabel accurate convex relaxation of vectorial multilabel energies
sublabel accurate convex relaxation of vectorial multilabel energiesFujimoto Keisuke
 
PRML輪読#14
PRML輪読#14PRML輪読#14
PRML輪読#14matsuolab
 
Fractality of Massive Graphs: Scalable Analysis with Sketch-Based Box-Coverin...
Fractality of Massive Graphs: Scalable Analysis with Sketch-Based Box-Coverin...Fractality of Massive Graphs: Scalable Analysis with Sketch-Based Box-Coverin...
Fractality of Massive Graphs: Scalable Analysis with Sketch-Based Box-Coverin...Kenko Nakamura
 
Practical recommendations for gradient-based training of deep architectures
Practical recommendations for gradient-based training of deep architecturesPractical recommendations for gradient-based training of deep architectures
Practical recommendations for gradient-based training of deep architecturesKoji Matsuda
 
ORB-SLAMを動かしてみた
ORB-SLAMを動かしてみたORB-SLAMを動かしてみた
ORB-SLAMを動かしてみたTakuya Minagawa
 
強化学習その2
強化学習その2強化学習その2
強化学習その2nishio
 
多項式あてはめで眺めるベイズ推定 ~今日からきみもベイジアン~
多項式あてはめで眺めるベイズ推定~今日からきみもベイジアン~多項式あてはめで眺めるベイズ推定~今日からきみもベイジアン~
多項式あてはめで眺めるベイズ推定 ~今日からきみもベイジアン~ tanutarou
 
LiDAR点群とSfM点群との位置合わせ
LiDAR点群とSfM点群との位置合わせLiDAR点群とSfM点群との位置合わせ
LiDAR点群とSfM点群との位置合わせTakuya Minagawa
 
画像認識モデルを作るための鉄板レシピ
画像認識モデルを作るための鉄板レシピ画像認識モデルを作るための鉄板レシピ
画像認識モデルを作るための鉄板レシピTakahiro Kubo
 

Viewers also liked (15)

CVPR2016読み会 Sparsifying Neural Network Connections for Face Recognition
CVPR2016読み会 Sparsifying Neural Network Connections for Face RecognitionCVPR2016読み会 Sparsifying Neural Network Connections for Face Recognition
CVPR2016読み会 Sparsifying Neural Network Connections for Face Recognition
 
20170819 CV勉強会 CVPR 2017
20170819 CV勉強会 CVPR 201720170819 CV勉強会 CVPR 2017
20170819 CV勉強会 CVPR 2017
 
On the Dynamics of Machine Learning Algorithms and Behavioral Game Theory
On the Dynamics of Machine Learning Algorithms and Behavioral Game TheoryOn the Dynamics of Machine Learning Algorithms and Behavioral Game Theory
On the Dynamics of Machine Learning Algorithms and Behavioral Game Theory
 
Stochastic Variational Inference
Stochastic Variational InferenceStochastic Variational Inference
Stochastic Variational Inference
 
DeepLearningTutorial
DeepLearningTutorialDeepLearningTutorial
DeepLearningTutorial
 
Greed is Good: 劣モジュラ関数最大化とその発展
Greed is Good: 劣モジュラ関数最大化とその発展Greed is Good: 劣モジュラ関数最大化とその発展
Greed is Good: 劣モジュラ関数最大化とその発展
 
sublabel accurate convex relaxation of vectorial multilabel energies
sublabel accurate convex relaxation of vectorial multilabel energiessublabel accurate convex relaxation of vectorial multilabel energies
sublabel accurate convex relaxation of vectorial multilabel energies
 
PRML輪読#14
PRML輪読#14PRML輪読#14
PRML輪読#14
 
Fractality of Massive Graphs: Scalable Analysis with Sketch-Based Box-Coverin...
Fractality of Massive Graphs: Scalable Analysis with Sketch-Based Box-Coverin...Fractality of Massive Graphs: Scalable Analysis with Sketch-Based Box-Coverin...
Fractality of Massive Graphs: Scalable Analysis with Sketch-Based Box-Coverin...
 
Practical recommendations for gradient-based training of deep architectures
Practical recommendations for gradient-based training of deep architecturesPractical recommendations for gradient-based training of deep architectures
Practical recommendations for gradient-based training of deep architectures
 
ORB-SLAMを動かしてみた
ORB-SLAMを動かしてみたORB-SLAMを動かしてみた
ORB-SLAMを動かしてみた
 
強化学習その2
強化学習その2強化学習その2
強化学習その2
 
多項式あてはめで眺めるベイズ推定 ~今日からきみもベイジアン~
多項式あてはめで眺めるベイズ推定~今日からきみもベイジアン~多項式あてはめで眺めるベイズ推定~今日からきみもベイジアン~
多項式あてはめで眺めるベイズ推定 ~今日からきみもベイジアン~
 
LiDAR点群とSfM点群との位置合わせ
LiDAR点群とSfM点群との位置合わせLiDAR点群とSfM点群との位置合わせ
LiDAR点群とSfM点群との位置合わせ
 
画像認識モデルを作るための鉄板レシピ
画像認識モデルを作るための鉄板レシピ画像認識モデルを作るための鉄板レシピ
画像認識モデルを作るための鉄板レシピ
 

Similar to プログラミングコンテストでのデータ構造 2 ~動的木編~

純粋関数型アルゴリズム入門
純粋関数型アルゴリズム入門純粋関数型アルゴリズム入門
純粋関数型アルゴリズム入門Kimikazu Kato
 
PFDS 5.5 Pairing heap
PFDS 5.5 Pairing heapPFDS 5.5 Pairing heap
PFDS 5.5 Pairing heap昌平 村山
 
Real World OCamlを読んでLispと協調してみた
Real World OCamlを読んでLispと協調してみたReal World OCamlを読んでLispと協調してみた
Real World OCamlを読んでLispと協調してみたblackenedgold
 
数式をnumpyに落としこむコツ
数式をnumpyに落としこむコツ数式をnumpyに落としこむコツ
数式をnumpyに落としこむコツShuyo Nakatani
 
Lisp tutorial for Pythonista : Day 1
Lisp tutorial for Pythonista : Day 1Lisp tutorial for Pythonista : Day 1
Lisp tutorial for Pythonista : Day 1Ransui Iso
 
USP友の会勉強会、状態遷移図の巻
USP友の会勉強会、状態遷移図の巻USP友の会勉強会、状態遷移図の巻
USP友の会勉強会、状態遷移図の巻Ryuichi Ueda
 
Lisp tutorial for Pythonista : Day 2
Lisp tutorial for Pythonista : Day 2Lisp tutorial for Pythonista : Day 2
Lisp tutorial for Pythonista : Day 2Ransui Iso
 
R による文書分類入門
R による文書分類入門R による文書分類入門
R による文書分類入門Takeshi Arabiki
 
IbisPaintのOpenGLES2.0
IbisPaintのOpenGLES2.0IbisPaintのOpenGLES2.0
IbisPaintのOpenGLES2.0Eiji Kamiya
 
Lisp Tutorial for Pythonista : Day 3
Lisp Tutorial for Pythonista : Day 3Lisp Tutorial for Pythonista : Day 3
Lisp Tutorial for Pythonista : Day 3Ransui Iso
 
関数プログラミング入門
関数プログラミング入門関数プログラミング入門
関数プログラミング入門Hideyuki Tanaka
 
Lisp Tutorial for Pythonista : Day 5
Lisp Tutorial for Pythonista : Day 5Lisp Tutorial for Pythonista : Day 5
Lisp Tutorial for Pythonista : Day 5Ransui Iso
 
transformer解説~Chat-GPTの源流~
transformer解説~Chat-GPTの源流~transformer解説~Chat-GPTの源流~
transformer解説~Chat-GPTの源流~MasayoshiTsutsui
 
Material
MaterialMaterial
Material_TUNE_
 
Introduction to NumPy & SciPy
Introduction to NumPy & SciPyIntroduction to NumPy & SciPy
Introduction to NumPy & SciPyShiqiao Du
 
PRML復々習レーン#9 6.3-6.3.1
PRML復々習レーン#9 6.3-6.3.1PRML復々習レーン#9 6.3-6.3.1
PRML復々習レーン#9 6.3-6.3.1sleepy_yoshi
 

Similar to プログラミングコンテストでのデータ構造 2 ~動的木編~ (20)

純粋関数型アルゴリズム入門
純粋関数型アルゴリズム入門純粋関数型アルゴリズム入門
純粋関数型アルゴリズム入門
 
PFDS 5.5 Pairing heap
PFDS 5.5 Pairing heapPFDS 5.5 Pairing heap
PFDS 5.5 Pairing heap
 
Real World OCamlを読んでLispと協調してみた
Real World OCamlを読んでLispと協調してみたReal World OCamlを読んでLispと協調してみた
Real World OCamlを読んでLispと協調してみた
 
数式をnumpyに落としこむコツ
数式をnumpyに落としこむコツ数式をnumpyに落としこむコツ
数式をnumpyに落としこむコツ
 
Lisp tutorial for Pythonista : Day 1
Lisp tutorial for Pythonista : Day 1Lisp tutorial for Pythonista : Day 1
Lisp tutorial for Pythonista : Day 1
 
USP友の会勉強会、状態遷移図の巻
USP友の会勉強会、状態遷移図の巻USP友の会勉強会、状態遷移図の巻
USP友の会勉強会、状態遷移図の巻
 
Lisp tutorial for Pythonista : Day 2
Lisp tutorial for Pythonista : Day 2Lisp tutorial for Pythonista : Day 2
Lisp tutorial for Pythonista : Day 2
 
T77 episteme
T77 epistemeT77 episteme
T77 episteme
 
R による文書分類入門
R による文書分類入門R による文書分類入門
R による文書分類入門
 
IbisPaintのOpenGLES2.0
IbisPaintのOpenGLES2.0IbisPaintのOpenGLES2.0
IbisPaintのOpenGLES2.0
 
Lisp Tutorial for Pythonista : Day 3
Lisp Tutorial for Pythonista : Day 3Lisp Tutorial for Pythonista : Day 3
Lisp Tutorial for Pythonista : Day 3
 
PFI Christmas seminar 2009
PFI Christmas seminar 2009PFI Christmas seminar 2009
PFI Christmas seminar 2009
 
関数プログラミング入門
関数プログラミング入門関数プログラミング入門
関数プログラミング入門
 
Lisp Tutorial for Pythonista : Day 5
Lisp Tutorial for Pythonista : Day 5Lisp Tutorial for Pythonista : Day 5
Lisp Tutorial for Pythonista : Day 5
 
transformer解説~Chat-GPTの源流~
transformer解説~Chat-GPTの源流~transformer解説~Chat-GPTの源流~
transformer解説~Chat-GPTの源流~
 
Material
MaterialMaterial
Material
 
Introduction to NumPy & SciPy
Introduction to NumPy & SciPyIntroduction to NumPy & SciPy
Introduction to NumPy & SciPy
 
PRML復々習レーン#9 6.3-6.3.1
PRML復々習レーン#9 6.3-6.3.1PRML復々習レーン#9 6.3-6.3.1
PRML復々習レーン#9 6.3-6.3.1
 
HPC Phys-20201203
HPC Phys-20201203HPC Phys-20201203
HPC Phys-20201203
 
20120127 nhn
20120127 nhn20120127 nhn
20120127 nhn
 

More from Takuya Akiba

分散深層学習 @ NIPS'17
分散深層学習 @ NIPS'17分散深層学習 @ NIPS'17
分散深層学習 @ NIPS'17Takuya Akiba
 
Learning Convolutional Neural Networks for Graphs
Learning Convolutional Neural Networks for GraphsLearning Convolutional Neural Networks for Graphs
Learning Convolutional Neural Networks for GraphsTakuya Akiba
 
TCO15 Algorithm Round 2C 解説
TCO15 Algorithm Round 2C 解説TCO15 Algorithm Round 2C 解説
TCO15 Algorithm Round 2C 解説Takuya Akiba
 
ACM-ICPC 世界大会 2015 問題 K "Tours" 解説
ACM-ICPC 世界大会 2015 問題 K "Tours" 解説ACM-ICPC 世界大会 2015 問題 K "Tours" 解説
ACM-ICPC 世界大会 2015 問題 K "Tours" 解説Takuya Akiba
 
大規模グラフ解析のための乱択スケッチ技法
大規模グラフ解析のための乱択スケッチ技法大規模グラフ解析のための乱択スケッチ技法
大規模グラフ解析のための乱択スケッチ技法Takuya Akiba
 
乱択データ構造の最新事情 -MinHash と HyperLogLog の最近の進歩-
乱択データ構造の最新事情 -MinHash と HyperLogLog の最近の進歩-乱択データ構造の最新事情 -MinHash と HyperLogLog の最近の進歩-
乱択データ構造の最新事情 -MinHash と HyperLogLog の最近の進歩-Takuya Akiba
 
Cache-Oblivious データ構造入門 @DSIRNLP#5
Cache-Oblivious データ構造入門 @DSIRNLP#5Cache-Oblivious データ構造入門 @DSIRNLP#5
Cache-Oblivious データ構造入門 @DSIRNLP#5Takuya Akiba
 
平面グラフと交通ネットワークのアルゴリズム
平面グラフと交通ネットワークのアルゴリズム平面グラフと交通ネットワークのアルゴリズム
平面グラフと交通ネットワークのアルゴリズムTakuya Akiba
 
大規模ネットワークの性質と先端グラフアルゴリズム
大規模ネットワークの性質と先端グラフアルゴリズム大規模ネットワークの性質と先端グラフアルゴリズム
大規模ネットワークの性質と先端グラフアルゴリズムTakuya Akiba
 
勉強か?趣味か?人生か?―プログラミングコンテストとは
勉強か?趣味か?人生か?―プログラミングコンテストとは勉強か?趣味か?人生か?―プログラミングコンテストとは
勉強か?趣味か?人生か?―プログラミングコンテストとはTakuya Akiba
 
大規模グラフアルゴリズムの最先端
大規模グラフアルゴリズムの最先端大規模グラフアルゴリズムの最先端
大規模グラフアルゴリズムの最先端Takuya Akiba
 
プログラミングコンテストでの動的計画法
プログラミングコンテストでの動的計画法プログラミングコンテストでの動的計画法
プログラミングコンテストでの動的計画法Takuya Akiba
 

More from Takuya Akiba (12)

分散深層学習 @ NIPS'17
分散深層学習 @ NIPS'17分散深層学習 @ NIPS'17
分散深層学習 @ NIPS'17
 
Learning Convolutional Neural Networks for Graphs
Learning Convolutional Neural Networks for GraphsLearning Convolutional Neural Networks for Graphs
Learning Convolutional Neural Networks for Graphs
 
TCO15 Algorithm Round 2C 解説
TCO15 Algorithm Round 2C 解説TCO15 Algorithm Round 2C 解説
TCO15 Algorithm Round 2C 解説
 
ACM-ICPC 世界大会 2015 問題 K "Tours" 解説
ACM-ICPC 世界大会 2015 問題 K "Tours" 解説ACM-ICPC 世界大会 2015 問題 K "Tours" 解説
ACM-ICPC 世界大会 2015 問題 K "Tours" 解説
 
大規模グラフ解析のための乱択スケッチ技法
大規模グラフ解析のための乱択スケッチ技法大規模グラフ解析のための乱択スケッチ技法
大規模グラフ解析のための乱択スケッチ技法
 
乱択データ構造の最新事情 -MinHash と HyperLogLog の最近の進歩-
乱択データ構造の最新事情 -MinHash と HyperLogLog の最近の進歩-乱択データ構造の最新事情 -MinHash と HyperLogLog の最近の進歩-
乱択データ構造の最新事情 -MinHash と HyperLogLog の最近の進歩-
 
Cache-Oblivious データ構造入門 @DSIRNLP#5
Cache-Oblivious データ構造入門 @DSIRNLP#5Cache-Oblivious データ構造入門 @DSIRNLP#5
Cache-Oblivious データ構造入門 @DSIRNLP#5
 
平面グラフと交通ネットワークのアルゴリズム
平面グラフと交通ネットワークのアルゴリズム平面グラフと交通ネットワークのアルゴリズム
平面グラフと交通ネットワークのアルゴリズム
 
大規模ネットワークの性質と先端グラフアルゴリズム
大規模ネットワークの性質と先端グラフアルゴリズム大規模ネットワークの性質と先端グラフアルゴリズム
大規模ネットワークの性質と先端グラフアルゴリズム
 
勉強か?趣味か?人生か?―プログラミングコンテストとは
勉強か?趣味か?人生か?―プログラミングコンテストとは勉強か?趣味か?人生か?―プログラミングコンテストとは
勉強か?趣味か?人生か?―プログラミングコンテストとは
 
大規模グラフアルゴリズムの最先端
大規模グラフアルゴリズムの最先端大規模グラフアルゴリズムの最先端
大規模グラフアルゴリズムの最先端
 
プログラミングコンテストでの動的計画法
プログラミングコンテストでの動的計画法プログラミングコンテストでの動的計画法
プログラミングコンテストでの動的計画法
 

Recently uploaded

MPAなWebフレームワーク、Astroの紹介 (その1) 2024/05/17の勉強会で発表されたものです。
MPAなWebフレームワーク、Astroの紹介 (その1) 2024/05/17の勉強会で発表されたものです。MPAなWebフレームワーク、Astroの紹介 (その1) 2024/05/17の勉強会で発表されたものです。
MPAなWebフレームワーク、Astroの紹介 (その1) 2024/05/17の勉強会で発表されたものです。iPride Co., Ltd.
 
情報を表現するときのポイント
情報を表現するときのポイント情報を表現するときのポイント
情報を表現するときのポイントonozaty
 
Intranet Development v1.0 (TSG LIVE! 12 LT )
Intranet Development v1.0 (TSG LIVE! 12 LT )Intranet Development v1.0 (TSG LIVE! 12 LT )
Intranet Development v1.0 (TSG LIVE! 12 LT )iwashiira2ctf
 
LoRaWAN無位置ロープ型水漏れセンサー WL03A-LB/LSカタログ ファイル
LoRaWAN無位置ロープ型水漏れセンサー WL03A-LB/LSカタログ ファイルLoRaWAN無位置ロープ型水漏れセンサー WL03A-LB/LSカタログ ファイル
LoRaWAN無位置ロープ型水漏れセンサー WL03A-LB/LSカタログ ファイルCRI Japan, Inc.
 
ロボットマニピュレーションの作業・動作計画 / rosjp_planning_for_robotic_manipulation_20240521
ロボットマニピュレーションの作業・動作計画 / rosjp_planning_for_robotic_manipulation_20240521ロボットマニピュレーションの作業・動作計画 / rosjp_planning_for_robotic_manipulation_20240521
ロボットマニピュレーションの作業・動作計画 / rosjp_planning_for_robotic_manipulation_20240521Satoshi Makita
 
論文紹介:ViTPose: Simple Vision Transformer Baselines for Human Pose Estimation
論文紹介:ViTPose: Simple Vision Transformer Baselines for Human Pose Estimation論文紹介:ViTPose: Simple Vision Transformer Baselines for Human Pose Estimation
論文紹介:ViTPose: Simple Vision Transformer Baselines for Human Pose EstimationToru Tamaki
 
ネットワーク可視化 振る舞い検知(NDR)ご紹介_キンドリル202405.pdf
ネットワーク可視化 振る舞い検知(NDR)ご紹介_キンドリル202405.pdfネットワーク可視化 振る舞い検知(NDR)ご紹介_キンドリル202405.pdf
ネットワーク可視化 振る舞い検知(NDR)ご紹介_キンドリル202405.pdfTakayuki Nakayama
 
クラウド時代におけるSREとUPWARDの取組ーUPWARD株式会社 CTO門畑
クラウド時代におけるSREとUPWARDの取組ーUPWARD株式会社 CTO門畑クラウド時代におけるSREとUPWARDの取組ーUPWARD株式会社 CTO門畑
クラウド時代におけるSREとUPWARDの取組ーUPWARD株式会社 CTO門畑Akihiro Kadohata
 
5/22 第23回 Customer系エンジニア座談会のスライド 公開用 西口瑛一
5/22 第23回 Customer系エンジニア座談会のスライド 公開用 西口瑛一5/22 第23回 Customer系エンジニア座談会のスライド 公開用 西口瑛一
5/22 第23回 Customer系エンジニア座談会のスライド 公開用 西口瑛一瑛一 西口
 
Keywordmap overview material/CINC.co.ltd
Keywordmap overview material/CINC.co.ltdKeywordmap overview material/CINC.co.ltd
Keywordmap overview material/CINC.co.ltdkokinagano2
 
研究紹介スライド: オフライン強化学習に基づくロボティックスワームの制御器の設計
研究紹介スライド: オフライン強化学習に基づくロボティックスワームの制御器の設計研究紹介スライド: オフライン強化学習に基づくロボティックスワームの制御器の設計
研究紹介スライド: オフライン強化学習に基づくロボティックスワームの制御器の設計atsushi061452
 
20240523_IoTLT_vol111_kitazaki_v1___.pdf
20240523_IoTLT_vol111_kitazaki_v1___.pdf20240523_IoTLT_vol111_kitazaki_v1___.pdf
20240523_IoTLT_vol111_kitazaki_v1___.pdfAyachika Kitazaki
 
Hyperledger Fabricコミュニティ活動体験& Hyperledger Fabric最新状況ご紹介
Hyperledger Fabricコミュニティ活動体験& Hyperledger Fabric最新状況ご紹介Hyperledger Fabricコミュニティ活動体験& Hyperledger Fabric最新状況ご紹介
Hyperledger Fabricコミュニティ活動体験& Hyperledger Fabric最新状況ご紹介Hyperleger Tokyo Meetup
 
Amazon Cognitoで実装するパスキー (Security-JAWS【第33回】 勉強会)
Amazon Cognitoで実装するパスキー (Security-JAWS【第33回】 勉強会)Amazon Cognitoで実装するパスキー (Security-JAWS【第33回】 勉強会)
Amazon Cognitoで実装するパスキー (Security-JAWS【第33回】 勉強会)keikoitakurag
 
2024年5月17日 先駆的科学計算フォーラム2024 機械学習を用いた新たなゲーム体験の創出の応用
2024年5月17日 先駆的科学計算フォーラム2024 機械学習を用いた新たなゲーム体験の創出の応用2024年5月17日 先駆的科学計算フォーラム2024 機械学習を用いた新たなゲーム体験の創出の応用
2024年5月17日 先駆的科学計算フォーラム2024 機械学習を用いた新たなゲーム体験の創出の応用KLab Inc. / Tech
 
部内勉強会(IT用語ざっくり学習) 実施日:2024年5月17日(金) 対象者:営業部社員
部内勉強会(IT用語ざっくり学習) 実施日:2024年5月17日(金) 対象者:営業部社員部内勉強会(IT用語ざっくり学習) 実施日:2024年5月17日(金) 対象者:営業部社員
部内勉強会(IT用語ざっくり学習) 実施日:2024年5月17日(金) 対象者:営業部社員Sadaomi Nishi
 

Recently uploaded (16)

MPAなWebフレームワーク、Astroの紹介 (その1) 2024/05/17の勉強会で発表されたものです。
MPAなWebフレームワーク、Astroの紹介 (その1) 2024/05/17の勉強会で発表されたものです。MPAなWebフレームワーク、Astroの紹介 (その1) 2024/05/17の勉強会で発表されたものです。
MPAなWebフレームワーク、Astroの紹介 (その1) 2024/05/17の勉強会で発表されたものです。
 
情報を表現するときのポイント
情報を表現するときのポイント情報を表現するときのポイント
情報を表現するときのポイント
 
Intranet Development v1.0 (TSG LIVE! 12 LT )
Intranet Development v1.0 (TSG LIVE! 12 LT )Intranet Development v1.0 (TSG LIVE! 12 LT )
Intranet Development v1.0 (TSG LIVE! 12 LT )
 
LoRaWAN無位置ロープ型水漏れセンサー WL03A-LB/LSカタログ ファイル
LoRaWAN無位置ロープ型水漏れセンサー WL03A-LB/LSカタログ ファイルLoRaWAN無位置ロープ型水漏れセンサー WL03A-LB/LSカタログ ファイル
LoRaWAN無位置ロープ型水漏れセンサー WL03A-LB/LSカタログ ファイル
 
ロボットマニピュレーションの作業・動作計画 / rosjp_planning_for_robotic_manipulation_20240521
ロボットマニピュレーションの作業・動作計画 / rosjp_planning_for_robotic_manipulation_20240521ロボットマニピュレーションの作業・動作計画 / rosjp_planning_for_robotic_manipulation_20240521
ロボットマニピュレーションの作業・動作計画 / rosjp_planning_for_robotic_manipulation_20240521
 
論文紹介:ViTPose: Simple Vision Transformer Baselines for Human Pose Estimation
論文紹介:ViTPose: Simple Vision Transformer Baselines for Human Pose Estimation論文紹介:ViTPose: Simple Vision Transformer Baselines for Human Pose Estimation
論文紹介:ViTPose: Simple Vision Transformer Baselines for Human Pose Estimation
 
ネットワーク可視化 振る舞い検知(NDR)ご紹介_キンドリル202405.pdf
ネットワーク可視化 振る舞い検知(NDR)ご紹介_キンドリル202405.pdfネットワーク可視化 振る舞い検知(NDR)ご紹介_キンドリル202405.pdf
ネットワーク可視化 振る舞い検知(NDR)ご紹介_キンドリル202405.pdf
 
クラウド時代におけるSREとUPWARDの取組ーUPWARD株式会社 CTO門畑
クラウド時代におけるSREとUPWARDの取組ーUPWARD株式会社 CTO門畑クラウド時代におけるSREとUPWARDの取組ーUPWARD株式会社 CTO門畑
クラウド時代におけるSREとUPWARDの取組ーUPWARD株式会社 CTO門畑
 
5/22 第23回 Customer系エンジニア座談会のスライド 公開用 西口瑛一
5/22 第23回 Customer系エンジニア座談会のスライド 公開用 西口瑛一5/22 第23回 Customer系エンジニア座談会のスライド 公開用 西口瑛一
5/22 第23回 Customer系エンジニア座談会のスライド 公開用 西口瑛一
 
Keywordmap overview material/CINC.co.ltd
Keywordmap overview material/CINC.co.ltdKeywordmap overview material/CINC.co.ltd
Keywordmap overview material/CINC.co.ltd
 
研究紹介スライド: オフライン強化学習に基づくロボティックスワームの制御器の設計
研究紹介スライド: オフライン強化学習に基づくロボティックスワームの制御器の設計研究紹介スライド: オフライン強化学習に基づくロボティックスワームの制御器の設計
研究紹介スライド: オフライン強化学習に基づくロボティックスワームの制御器の設計
 
20240523_IoTLT_vol111_kitazaki_v1___.pdf
20240523_IoTLT_vol111_kitazaki_v1___.pdf20240523_IoTLT_vol111_kitazaki_v1___.pdf
20240523_IoTLT_vol111_kitazaki_v1___.pdf
 
Hyperledger Fabricコミュニティ活動体験& Hyperledger Fabric最新状況ご紹介
Hyperledger Fabricコミュニティ活動体験& Hyperledger Fabric最新状況ご紹介Hyperledger Fabricコミュニティ活動体験& Hyperledger Fabric最新状況ご紹介
Hyperledger Fabricコミュニティ活動体験& Hyperledger Fabric最新状況ご紹介
 
Amazon Cognitoで実装するパスキー (Security-JAWS【第33回】 勉強会)
Amazon Cognitoで実装するパスキー (Security-JAWS【第33回】 勉強会)Amazon Cognitoで実装するパスキー (Security-JAWS【第33回】 勉強会)
Amazon Cognitoで実装するパスキー (Security-JAWS【第33回】 勉強会)
 
2024年5月17日 先駆的科学計算フォーラム2024 機械学習を用いた新たなゲーム体験の創出の応用
2024年5月17日 先駆的科学計算フォーラム2024 機械学習を用いた新たなゲーム体験の創出の応用2024年5月17日 先駆的科学計算フォーラム2024 機械学習を用いた新たなゲーム体験の創出の応用
2024年5月17日 先駆的科学計算フォーラム2024 機械学習を用いた新たなゲーム体験の創出の応用
 
部内勉強会(IT用語ざっくり学習) 実施日:2024年5月17日(金) 対象者:営業部社員
部内勉強会(IT用語ざっくり学習) 実施日:2024年5月17日(金) 対象者:営業部社員部内勉強会(IT用語ざっくり学習) 実施日:2024年5月17日(金) 対象者:営業部社員
部内勉強会(IT用語ざっくり学習) 実施日:2024年5月17日(金) 対象者:営業部社員
 

プログラミングコンテストでのデータ構造 2 ~動的木編~

  • 1. 2012/3/20 NTTデータ駒場研修所 (情報オリンピック春合宿) プログラミングコンテストでの データ構造2 ~動的木編~ 東京大学情報理工学系研究科 秋葉 拓哉 1
  • 2. 動的木 • 実は動的木にもいくつかある – 「順位キュー」的な言葉 (⇔ 二分ヒープ, フィボナッチヒープ) • ポピュラーな動的木 – Link-Cut 木 – Euler-Tour 木 (動的グラフで内部的に使う) • 今日は Link-Cut 木 の話をします 2
  • 3. Link-Cut 木 • 木を処理する神がかり的なデータ構造!! (木で木を処理するのでややこしい…) • 以下が 𝑂(log 𝑛) 時間でできる. – 頂点の親を変更 (link) / 削除 (cut) – 木の根を求める (root) / 木の根を変更 (evert) – パスに対する頂点・枝の値のクエリ (sum・max・更新など) 3
  • 4. Link-Cut 木は現実 そんなのどうせ実装できっこない… (´・_・`) IOI は Link-Cut 木で常勝!! Fan Haoqiang 氏 ※発言はフィクションです (中国) Fan Haoqiang 氏は IOI’11 の Elephants で Link-Cut 木を実装! • これに関して特別賞を受賞 • 599 点で準優勝 4
  • 5. …でもやっぱその前に! • 動的木は本当に必要?いつものじゃダメ? • やはり,実装が面倒,避けられたら避けたい • 実際のとこ,本当に必要になる問題は皆無 (特別賞を狙いたいのであればこの限りではない) 5
  • 6. 木上の距離クエリ • 2 頂点間の枝を作成・削除してください • 2 頂点間の距離を答えてください ただしグラフは常に森. ツリーを処理するデータ構造なんて他に知らない… 動的木じゃないとできっこないよ… (´・_・`) 平方分割でもできるよ (重要!!) ( ・`д・´) 6
  • 7. クエリを平方分割 クエリ • クエリを 𝐵 個ごとのブロックに分割 終わった • 各ブロック内で操作に関わる頂点は 部分 高々2𝐵個 • それ以外の頂点は興味が無いので, 今やる 部分 ブロックを処理する最初に,縮約 – 𝑂(𝐵) 頂点の森になる 7
  • 8. クエリを平方分割 クエリ 縮約 • すると各クエリは 𝑂(𝐵) で処理可 ← 𝑂(𝐵) 𝑂(𝑁) – 普通に 𝑂(𝐵) 頂点の木を探索するだけ … 縮約 ← 𝑄 𝑂(𝑁) 𝑂(𝐵) 𝑂 𝑁 + 𝑄𝐵 = 𝑂 𝑄 𝑁 時間 𝐵 … ↑ 縮約 𝐵= 𝑁 とした ← 𝑂(𝐵) 𝑂(𝑁) … ただし,クエリが先読みできないと無理 類似した問題と,より詳しい解説: http://acm-icpc.aitea.net/index.php?plugin=attach&refer=2010%2FPractice%2F%B2%C6%B9%E7%BD%C9%2F%B9%D6%C9%BE&openfile=2d.pdf 8
  • 9. レベル別 Link-Cut 木 オプション link, cut, evert, 辺質問・更新 頂点質問 頂点更新 (実装そこそこ) (実装一瞬) (実装少し) ベース expose (実装そこそこ) • オプションは独立に選んで実装可 • 「頂点質問」 = ある頂点から根までのパスにおける頂点の属 性の sum とか max とかのこと • 「頂点更新」 =とはパス上の頂点全部に x 足すとかのこと 9
  • 11. 基本アイディア パスへの分解は決まってない + 固定じゃない こうなってるかもしれないし こうなってるかも 11
  • 12. 核となる操作 expose(𝒗) 頂点 v から根へのパスを繋げる ←切れる v v 切 れ ↑ る 平衡二分探索木の split / merge を使う 12
  • 13. link, cut の雰囲気 • cut(𝑣): 𝑣 から親への辺を削除 • link(𝑣, 𝑤): 𝑣 の親を 𝑤 にする 平衡二分探索木を切ったり繋げたりするだけ w w cut v v link 13
  • 14. 頂点クエリ • sumv(𝑣): 頂点 v から根までの頂点たちに書いて ある数の和 (あるいは minv, maxv, …) やり方 • 平衡二分探索木に,部分木の和を持たせる • expose(𝑣) して,和を見るだけ 14
  • 15. 各操作の計算量 結論: スプレー木を用いるとならし 𝑂 log 𝑛 時間 𝑂 log 2 𝑛 時間の略証: • expose の計算量だけ考えれば良い (他は余裕) • 平衡二分探索木で管理されるパスに入る・出る枝の本数 をならし 𝑂 log 𝑛 本に抑えられれば良い 1 本 “入って” v v 2 本 “出た” 15
  • 16. • 出るためには入る必要がある,入る回数を抑えれば OK • 元の木の Heavy-Light Decomposition を考える • Light-Edge の本数を抑える – 各頂点から根までの Light Edge はそもそも 𝑂 log 𝑛 本 – よって,入る Light-Edgeは 𝑂 log 𝑛 本 • Heavy-Edge の本数を抑える – 1 度にいじる Heavy-Edge の本数は多いかも,でも, – Heavy-Edge が入るということは Light-Edge が出る – Light-Edge が出るためには Light-Edge が入ってるはず – それはさっき数えた! 各クエリ 𝑂 log 𝑛 本! – よってならし 𝑂 log 𝑛 本になる • よって 𝑂 log 𝑛 ならし本.よって 𝑂 log 2 𝑛 ならし時間. 16
  • 17. 各操作の計算量 𝑂 log 𝑛 時間: • スプレー木のポテンシャルに踏み入って解析する • 今日は省略 Link-Cut 木を実装していこう! (気合い!) (といってもスプレー木が出来れば殆ど終わり) 17
  • 18. 実装:ノードの構造体 struct node_t { node_t *pp, *lp, *rp; // 親,左の子,右の子 // このノードは木の根? bool is_root() { return !pp || (pp->lp != this && pp->rp != this); } … Is_root は何故 !pp だけじゃない? → pp をパスの親を表すのにも使うため (後述) (こうすると実装が凄い楽になります) 親でありながら子でないことがある 18
  • 19. 実装:ノードの構造体 (続き) void rotr() { // 右回転 void splay() { // スプレー操作 node_t *q = pp, *r = q->pp; while (!is_root()) { if ((q->lp = rp)) rp->pp = q; node_t *q = pp; rp = q; q->pp = this; if (q->is_root()) { if ((pp = r)) { if (q->lp == this) rotr(); if (r->lp == q) r->lp = this; else rotl(); if (r->rp == q) r->rp = this; } else { } node_t *r = q->pp; } if (r->lp == q) { if (q->lp == this) { q->rotr(); rotr(); } void rotl() { // 左回転 else { rotl(); rotr(); } node_t *q = pp, *r = q->pp; } else { if ((q->rp = lp)) lp->pp = q; if (q->rp == this) { q->rotl(); rotl(); } lp = q; q->pp = this; else { rotr(); rotl(); } if ((pp = r)) { } if (r->lp == q) r->lp = this; } if (r->rp == q) r->rp = this; } } } } スプレー操作を Bottom-Up の方式で実装する (普通に平衡二分探索木でスプレー木を使うときは Top-Down の方式の方が良いが, 今回はノードのポインタを知ってるところから splay したいので Bottom-Up) (参考:Top-Down の実装例 http://www.prefield.com/algorithm/container/splay_tree.html) 19
  • 20. 実装:パスの親 NULL 3 1 2 5 2 表現の例 1 4 a 3 b 4 a 5 c c b • pp (親へのポインタ) を 2 通りの使い方をすると楽 – 普通に二分探索木内での親へのポインタ(緑・青の両向き) – パスからの親へのポインタ (赤色の片方向) 20
  • 21. expose(c) 1 1 2 2 3 a 3 a b 4 b 4 c 5 5 c NULL NULL 2 2 1 3 1 3 5 5 4 4 a a c c b b ノード 2 の右の子を こうなってたら 3 から a にするだけ! 21
  • 22. 実装:expose やること: node_t *expose(node_t *x) { node_t *rp = NULL; 1. 今いる頂点を splay for (node_t *p = x; p; p = p->pp) { p->splay(); 2. 右側にさっきまで居た木を p->rp = rp; rp = p; くっつける } x->splay(); // しとくと便利 3. 上の木に進む return x; } 3 3 2 2 3 2 5 2 5 1 1 c 5 1 4 1 4 4 a b a c c c a a 3 5 b b b 4 さいしょ Splay(c) 2 に移動,splay(2) 2 の右に c をつける 22
  • 23. 実装:link, cut expose まで出来ていればもう簡単 void cut(node_t *c) { expose(c); cut p node_t *p = c->lp; • c を expose c c->lp = NULL; p->pp = NULL; • c の左を切断 } link cut void link(node_t *c, node_t *p) { expose(c); link expose(p); • c, p を expose p c->pp = p; • p の右に c を c p->rp = c; つける } 23
  • 24. 実装:evert evert(𝑣):𝑣 を根にする 木のパスの向きを反転すればよい v void evert(node_t *p) { node_t *r = expose(p); r->rev = true; v } + スプレー木に 反転の機能を実装 24
  • 25. 実装:辺属性 • 木の辺に情報をつける • 回転とか張替えでポインタと一緒に情報を保つ (注意深く) • 部分木に関する情報も保つ NULL 2 3 3 1 1 1 2 4 5 2 2 5 1 5 4 a 3 3 6 a b 4 4 6 7 5 c c b 7 25
  • 26. 応用:Elephants (IOI’11) • 象が 𝑁 匹並んでます • クエリが大量にくる – Update(𝑖, 𝑥) – i 匹目の象を場所 x に移動 • クエリの度に答える – 何台のカメラで全員写る? – カメラ:幅 𝐿 26
  • 27. 応用:Elephants (IOI’11) • 愚直な解法:クエリ毎に計算する – 貪欲法の典型的問題 – 一番左の象を覆う,を繰り返せば良い • 動的木を使う解法: – 似たような感じのことを木で表現する – 移動は木のちょっとした更新になる – よってクエリに爆速で答えられる 27
  • 28. 応用:Elephants (IOI’11) • 象の場所に ● を書く • そこから L 先に ○ を書き,●から辺を張る • ○からはすぐ次の●か○に辺を張る • これはツリー! • 一番左から辿って,●の個数が答え! 28
  • 29. Link-Cut 木まとめ • まずはもっと容易な道具を検討! – クエリの平方分割 • 実装しよう (下に行くほど大変) – expose, link, cut, root, 頂点の情報に関する質問 – evert, 頂点の情報の更新 – 辺の情報に関する質問・更新 29
  • 30. 全体まとめと私見 話したこと • 平衡二分探索木 – 本当に必要か検討,必要な場所だけ作るセグメント木 – Treapのアイディア,楽な実装法の議論,応用例 – その他の平衡二分探索木の紹介 • 動的木 – 本当に必要か検討,クエリの平方分割 – Link-Cut Tree のアイディア,楽な実装法の議論,応用例 私見 • これらは難易度が高く,想定解法としての出題頻度は低い • よって,習得の優先度は高くない • ただし,非常に強力な道具なので,武器にできれば得をするかも? 30