-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
b8961e5
commit beae19a
Showing
1 changed file
with
142 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,142 @@ | ||
--- | ||
title: Static top tree | ||
documentation_of: ./static_toptree.hpp | ||
--- | ||
|
||
いわゆる Static top tree を扱う.根付き木の部分木に関する各種演算をクエリあたり $O(n \log n)$ で行える. | ||
|
||
## 原理 | ||
|
||
Static top tree のしくみについては [解説 - AtCoder Beginner Contest 351](https://atcoder.jp/contests/abc351/editorial/9868) 等も併せて参照されたい. | ||
|
||
Static top tree は,根付き木をもとに平衡二分木を構築する.平衡二分木の各頂点には `PointCluster` と `PathCluster` の 2 種類のデータ構造のいずれかが載る. | ||
|
||
例えば,入力として以下の根付き木($0$ が根)を与えた場合に構築される static top tree を下に示す. | ||
|
||
![input](http://g.gravizo.com/svg? | ||
graph { | ||
v0 [label=0, shape=circle]; | ||
v1 [label=1, shape=circle]; | ||
v2 [label=2, shape=circle]; | ||
v3 [label=3, shape=circle]; | ||
v4 [label=4, shape=circle]; | ||
v5 [label=5, shape=circle]; | ||
v6 [label=6, shape=circle]; | ||
v7 [label=7, shape=circle]; | ||
v8 [label=8, shape=circle]; | ||
invisible1 [label="", style=invis]; | ||
invisible2 [label="", style=invis]; | ||
v0 -- v1 [color="black:invis:black", len=1]; | ||
v0 -- v8 [style="dashed"]; | ||
v1 -- v2 [color="black:invis:black", len=1]; | ||
v1 -- invisible1 [color="invis", len=1]; | ||
v2 -- v3 [color="black:invis:black", len=1]; | ||
v2 -- v4 [style="dashed"]; | ||
v2 -- v5 [style="dashed"]; | ||
v2 -- v7 [style="dashed"]; | ||
v5 -- v6 [color="black:invis:black", len=1]; | ||
v5 -- invisible2 [color="invis", len=1]; | ||
} | ||
) | ||
|
||
![出力](http://g.gravizo.com/g? | ||
graph { | ||
compress0123 [label="Compress", shape=oval] | ||
compress01 [label="Compress", shape=oval] | ||
compress23 [label="Compress", shape=oval] | ||
compress56 [label="Compress", shape=oval] | ||
|
||
vertex0 [label="AddVertex\n(0)", shape=oval] | ||
vertex1 [label="Vertex\n(1)", shape=oval] | ||
vertex2 [label="AddVertex\n(2)", shape=oval] | ||
vertex3 [label="Vertex\n(3)", shape=oval] | ||
vertex4 [label="Vertex\n(4)", shape=oval] | ||
vertex5 [label="Vertex\n(5)", shape=oval] | ||
vertex6 [label="Vertex\n(6)", shape=oval] | ||
vertex7 [label="Vertex\n(7)", shape=oval] | ||
vertex8 [label="Vertex\n(8)", shape=oval] | ||
|
||
rake4567 [label="Rake", shape=oval] | ||
rake456 [label="Rake", shape=oval] | ||
addedge4 [label="AddEdge", shape=oval] | ||
addedge56 [label="AddEdge", shape=oval] | ||
addedge7 [label="AddEdge", shape=oval] | ||
addedge8 [label="AddEdge", shape=oval] | ||
|
||
vertex0 -- addedge8 [style=dashed] | ||
|
||
addedge8 -- vertex8 | ||
|
||
compress0123 -- compress01 | ||
compress0123 -- compress23 | ||
compress01 -- vertex0 | ||
compress01 -- vertex1 | ||
compress23 -- vertex2 | ||
compress23 -- vertex3 | ||
|
||
vertex2 -- rake4567 [style=dashed] | ||
|
||
rake4567 -- rake456 [style=dashed] | ||
rake4567 -- addedge7 [style=dashed] | ||
addedge7 -- vertex7 | ||
|
||
rake456 -- addedge4 [style=dashed] | ||
rake456 -- addedge56 [style=dashed] | ||
|
||
addedge4 -- vertex4 | ||
|
||
addedge56 -- compress56 | ||
|
||
compress56 -- vertex5 | ||
compress56 -- vertex6 | ||
} | ||
) | ||
|
||
ここで入力の木の辺のうち二重線は heavy-light decomposition の heavy edge, 破線は light edge を示す.出力の辺のうち実線は PathCluster, 破線は PointCluster が親頂点に伝播されることをそれぞれ意味する. | ||
|
||
## 使用方法 | ||
|
||
まず,以下のように `Point` クラス・ `Path` クラスと `vertex()` / `compress()` / `rake()` / `add_edge()` / `add_vertex()` メソッドを持つクラスを定義する( `static` はなくても可). | ||
|
||
```cpp | ||
struct tree_dp { | ||
// Point Cluster | ||
struct Point {}; | ||
|
||
// Path Cluster | ||
struct Path {}; | ||
|
||
Path vertex(int i); | ||
|
||
static Path compress(const Path &parent, const Path &child); | ||
|
||
static Point rake(const Point &l, const Point &r); | ||
|
||
static Point add_edge(const Path &d); | ||
|
||
Path add_vertex(const Point &d, int i); | ||
}; | ||
``` | ||
その後,以下の手順で構築・利用する. | ||
```cpp | ||
// 前準備 | ||
vector<vector<int>> to; // 隣接リスト | ||
int root = 0; | ||
// 構築 | ||
const static_toptree_structure stts(to, root); | ||
tree_dp dp; | ||
static_toptree tree(stts, dp); | ||
// 利用 | ||
tree.set(u); // 頂点 u に更新があった場合に呼ぶ | ||
auto p = tree.all_prod(); // 根に関して値取得 | ||
``` | ||
|
||
## 問題例 | ||
|
||
- [AtCoder Beginner Contest 351 G - Hash on Tree](https://atcoder.jp/contests/abc351/tasks/abc351_g) | ||
- [Library Checker: Point Set Tree Path Composite Sum (Fixed Root)](https://judge.yosupo.jp/problem/point_set_tree_path_composite_sum_fixed_root) |