Skip to content

Commit efa475b

Browse files
hitonanodeweb-flow
andauthored
lca_rmq: repeated call of build() (#232)
* lca_rmq: repeated call of build() * [auto-verifier] verify commit 157d934 Co-authored-by: GitHub <noreply@github.com>
1 parent cdafe1c commit efa475b

File tree

4 files changed

+22
-13
lines changed

4 files changed

+22
-13
lines changed

.verify-helper/timestamps.remote.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,7 @@
220220
"tree/test/jump_on_tree.test.cpp": "2022-07-31 01:04:01 +0900",
221221
"tree/test/lca.test.cpp": "2022-07-31 01:04:01 +0900",
222222
"tree/test/lca.yuki898.test.cpp": "2022-07-31 01:04:01 +0900",
223-
"tree/test/lca_rmq.test.cpp": "2022-01-08 20:23:44 +0900",
223+
"tree/test/lca_rmq.test.cpp": "2022-09-24 13:23:24 +0900",
224224
"tree/test/rerooting.aoj1595.test.cpp": "2021-10-23 00:38:09 +0900",
225225
"tree/test/rerooting.yuki1718.test.cpp": "2021-10-23 00:38:09 +0900",
226226
"tree/test/tree_isomorphism.aoj1613.test.cpp": "2022-07-12 00:34:46 +0900",

tree/lca_rmq.hpp

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,11 @@
55
#include <utility>
66
#include <vector>
77

8-
// CUT begin
98
struct TreeLCA {
109
const int N;
1110
std::vector<std::vector<int>> to;
12-
bool built;
13-
TreeLCA(int V = 0) : N(V), to(V), built(false) {}
11+
int root;
12+
TreeLCA(int V = 0) : N(V), to(V), root(-1) {}
1413

1514
void add_edge(int u, int v) {
1615
assert(0 <= u and u < N);
@@ -37,25 +36,29 @@ struct TreeLCA {
3736
}
3837

3938
StaticRMQ<P> rmq;
40-
void build(int root = 0) {
41-
assert(root >= 0 and root < N);
42-
built = true;
43-
subtree_begin.resize(N);
39+
void build(int root_) {
40+
assert(root_ >= 0 and root_ < N);
41+
if (root == root_) return;
42+
root = root_;
43+
subtree_begin.assign(N, 0);
44+
vis_order.clear();
4445
vis_order.reserve(N * 2);
45-
depth.resize(N);
46+
depth.assign(N, 0);
4647
_build_dfs(root, -1, 0);
4748
rmq = {vis_order, P{N, -1}};
4849
}
4950

50-
int lca(int u, int v) {
51+
bool built() const noexcept { return root >= 0; }
52+
53+
int lca(int u, int v) const {
5154
assert(0 <= u and u < N);
5255
assert(0 <= v and v < N);
53-
if (!built) build();
56+
assert(built());
5457

55-
auto a = subtree_begin[u], b = subtree_begin[v];
58+
int a = subtree_begin[u], b = subtree_begin[v];
5659
if (a > b) std::swap(a, b);
5760
return rmq.get(a, b + 1).second;
5861
};
5962

60-
int path_length(int u, int v) { return depth[u] + depth[v] - depth[lca(u, v)] * 2; }
63+
int path_length(int u, int v) const { return depth[u] + depth[v] - depth[lca(u, v)] * 2; }
6164
};

tree/lca_rmq.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ documentation_of: ./lca_rmq.hpp
77

88
## 使用方法
99

10+
`add_edge(int u, int v)` を $N - 1$ 回行って木を構築した後,`build(int root)` によって根を指定する.
11+
1012
```cpp
1113
TreeLCA tree(N);
1214
for (int e = 0; e < N - 1; e++) {
@@ -15,6 +17,8 @@ for (int e = 0; e < N - 1; e++) {
1517
tree.add_edge(u, v);
1618
}
1719

20+
tree.build(0);
21+
1822
cout << tree.lca(a, b) << '\n'; // (a, b) の最長共通祖先
1923
cout << tree.path_length(a, b) << '\n'; // 2 頂点 a, b の距離
2024
```

tree/test/lca_rmq.test.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,7 @@ int main() {
1111
TreeLCA tree(N);
1212
for (int i = 1; i <= N - 1; i++) cin >> p, tree.add_edge(i, p);
1313

14+
tree.build(0);
15+
1416
while (Q--) cout << tree.lca((cin >> u, u), (cin >> v, v)) << '\n';
1517
}

0 commit comments

Comments
 (0)