Upgrade to Pro — share decks privately, control downloads, hide ads and more …

DSU on Tree

camypaper
November 07, 2017
3.4k

DSU on Tree

camypaper

November 07, 2017
Tweet

Transcript

  1. Q:ツリー上のマージテク亜種? A: CF383 Div.1 D の想定解で紹介されたやつ - (本家ではGuni(英語だとsackの意味)で呼ばれる) - (日本語では)名前はまだない?

    詳しくは以下を見た方がよい http://codeforces.com/blog/entry/44351 僕の理解をもとにかいつまんで紹介 - 正確には彼らが紹介したい方法とはちょっと違います(上のURLでの3番)
  2. 問題 • N 頂点の K 種類の色で頂点彩色された 根付き木が与えられる • 頂点 i

    は色 Ci で塗られている • 以下の Q 個のクエリを処理せよ – 頂点 ai を根とする部分木に含まれる 色 bi で塗られた頂点の数を求めよ • N, Q, K ≦ 105 ぐらい
  3. 解法 • mapに(色, 個数)を持ってdfsしながら マージをがんばる – mapどうしはマージテクでマージ • O(N log2N)

    でできる – unordered_map を使うとlogが一個落ちる – でも重い • 今回は O(N logN) で軽めの定数倍で やります、という話
  4. 用意する関数 • dfs1(v) – v を根とする根付き木について処理 – 結果として 「v を根とする部分木に含まれる

    各色の頂点がいくつあるか」を返す • dfs2(v) – v を根とする根付き木について処理 – 結果は返さない
  5. dfs1(v) • v の直接の子孫を u1 , u2 , u3 ,

    … , uk とする – 部分木のサイズの降順で並んでいる,とする • u2 , u3 , u4 , … , uk についてdfs2で処理 • u1 についてdfs1で処理して結果を受け取る – これを A とする • u2 , u3 , u4 , … , uk を根とする部分木に 含まれる頂点の色を全て調べて A に加算 • v 自身の色を A に加算 – このタイミングでクエリについて処理 • A を返す
  6. dfs2(v) • v の直接の子孫を u1 , u2 , u3 ,

    … , uk とする – 部分木のサイズの降順で並んでいる,とする • u2 , u3 , u4 , … , uk についてdfs2で処理 • u1 についてdfs1で処理して結果を受け取る – これを A とする • u2 , u3 , u4 , … , uk を根とする部分木に 含まれる頂点の色を全て調べて A に加算 • v 自身の色を A に加算 – このタイミングでクエリについて処理 • vを根とする部分木に含まれる頂点の色を 全て調べて A から減算
  7. Q: 疑問 Q1: A を作る度に O(K) じゃん Q2: dfs2 で

    A から減算するパートが 明らかに不要に見えるんだけど??? A: A は 1 回だけ作って使いまわして解決 (そのためにdfs2で A から減算する) (さっきは分かりやすさのために説明を省きました)
  8. アルゴリズム(簡易まとめ) • はじめに A を 1 個作る(使いまわす) • 根からdfsをする(dfs1でもdfs2でもよい) –

    子孫たちのうち,サイズが最大のもの以外をdfs2で処理 • A は全て 0 のまま – サイズが最大のものをdfs1で処理 • A にデータが入る – 子孫たちのうち,最大のもの以外を全て追加 – 自身を追加 • ここで A は部分木全体について処理された状態になる – クエリに答える – (dfs2なら)子孫たちのうち,最大のもの以外を全て削除 • 削除されると A は全て 0 になる
  9. • はじめに A を 1 個作る(使いまわす) • 根からdfsをする(dfs1でもdfs2でもよい) – 子孫たちのうち,サイズが最大のもの以外をdfs2で処理

    • A は全て 0 のまま – サイズが最大のものをdfs1で処理 • A にデータが入る – 子孫たちのうち,最大のもの以外を全て追加 – 自身を追加 • ここで A は部分木全体について処理された状態になる – クエリに答える – (dfs2なら)子孫たちのうち,最大のもの以外を全て削除 • 削除されると A は全て 0 になる アルゴリズム(簡易まとめ) この2つはさらに 別のdfs等で処理
  10. 計算量解析 • 各頂点についてdfs1 か dfs2 が 1 回行われる • dfs1,

    dfs2 で破線の先の部分木をなめる操作, dfs2 での最後に部分木を全てなめる操作の 2 つがボトルネック • ある頂点について,なめられる回数は O(logN) – 根にたどり着くまでに辿る破線の数の 2 倍回ぐらい なめられる – 破線はHL分解でのlight edgeなので O(logN) 回で済む • N 個の頂点があるから O(NlogN)
  11. まとめ • 各頂点を根とする部分木において 各色が含まれる数を求める,というのが 時間 O(NlogN), 空間 O(N + K)

    でできた • 利点と欠点 – unordered_mapを使うのに比べて定数倍が軽い – 実装はただマージテクするより少し重い