EulerTour Subtree
EulerTourの部分木を処理するバージョン
木を列に落とし込んだときの部分木の範囲がわかるので, Segment Treeと合わせて使うといい.
LCAをET Subtree + RMQで求める場合はコメントアウトしてある部分を使う.
Spec
-
eulertour_subtree(i64 n)
n
頂点の木を構築する準備
-
add_edge(i64 u, i64 v)
- 頂点
u
とv
を結ぶ辺を追加する
- 頂点
-
start_tour(i64 r)
r
を根としてEulerTourを行う- \( O(n) \)
-
subtree_range(i64 v)
- 頂点
v
の部分木に対応する範囲を返す - \( O(1) \)
- 頂点
-
vertex(i64 v)
- 頂点
v
に対応するindexを返す. - \( O(1) \)
- 頂点
Code
#include <bits/stdc++.h>
using namespace std;
using i64 = long long;
struct eulertour_subtree {
vector<vector<i64>> G;
vector<i64> tour;
vector<i64> L, R;
vector<i64> depth;
eulertour_subtree(i64 n): G(n), L(n), R(n), depth(n) {}
void add_edge(i64 u, i64 v) {
G[u].push_back(v);
G[v].push_back(u);
}
void dfs(i64 v, i64 f, i64 d) {
tour.push_back(v);
L[v] = tour.size() - 1;
depth[v] = d;
for(auto to: G[v]) {
if(to == f) continue;
dfs(to, v, d + 1);
//tour.push_back(v);
}
R[v] = tour.size() - 1;
}
void start_tour(i64 r) {
dfs(r, -1, 0);
}
//[L[v], R[v])
pair<i64, i64> subtree_range(i64 v) {
return pair<i64, i64>(L[v], R[v]);
}
i64 vertex(i64 v) {
return L[v];
}
};