Skip to content

Commit 9a63d9e

Browse files
lrvideckisweb-flow
andauthored
Linear rmq nits (#148)
* nits to linear lca * [auto-verifier] verify commit 5e627d0 * fix buggy test * [auto-verifier] verify commit 660858f --------- Co-authored-by: GitHub <noreply@github.com>
1 parent 3da36ae commit 9a63d9e

File tree

3 files changed

+21
-40
lines changed

3 files changed

+21
-40
lines changed

.verify-helper/timestamps.remote.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@
7272
"tests/library_checker_aizu_tests/handmade_tests/edge_cd_small_trees.test.cpp": "2025-04-27 21:47:37 -0600",
7373
"tests/library_checker_aizu_tests/handmade_tests/fib_matrix_expo.test.cpp": "2024-12-14 19:50:29 -0600",
7474
"tests/library_checker_aizu_tests/handmade_tests/functional_graph.test.cpp": "2025-07-08 19:28:25 -0600",
75-
"tests/library_checker_aizu_tests/handmade_tests/lca_ladder_forest.test.cpp": "2025-02-10 23:30:47 -0700",
75+
"tests/library_checker_aizu_tests/handmade_tests/lca_ladder_forest.test.cpp": "2025-08-03 23:02:28 -0600",
7676
"tests/library_checker_aizu_tests/handmade_tests/manacher.test.cpp": "2024-12-14 19:50:29 -0600",
7777
"tests/library_checker_aizu_tests/handmade_tests/merge_st_and_wavelet.test.cpp": "2025-07-10 12:34:21 -0600",
7878
"tests/library_checker_aizu_tests/handmade_tests/mobius.test.cpp": "2025-02-10 14:50:36 -0700",
@@ -133,9 +133,9 @@
133133
"tests/library_checker_aizu_tests/trees/edge_cd_count_paths_per_length.test.cpp": "2025-04-27 21:47:37 -0600",
134134
"tests/library_checker_aizu_tests/trees/edge_cd_reroot_dp.test.cpp": "2025-04-27 21:47:37 -0600",
135135
"tests/library_checker_aizu_tests/trees/kth_path_ladder.test.cpp": "2025-02-10 23:30:47 -0700",
136-
"tests/library_checker_aizu_tests/trees/kth_path_linear.test.cpp": "2025-02-10 23:30:47 -0700",
136+
"tests/library_checker_aizu_tests/trees/kth_path_linear.test.cpp": "2025-08-03 22:53:52 -0600",
137137
"tests/library_checker_aizu_tests/trees/kth_path_tree_lift.test.cpp": "2025-02-10 14:50:36 -0700",
138-
"tests/library_checker_aizu_tests/trees/lca_all_methods_aizu.test.cpp": "2025-02-10 14:50:36 -0700",
139-
"tests/library_checker_aizu_tests/trees/lca_all_methods_lib_checker.test.cpp": "2025-02-10 14:50:36 -0700",
138+
"tests/library_checker_aizu_tests/trees/lca_all_methods_aizu.test.cpp": "2025-08-03 22:53:52 -0600",
139+
"tests/library_checker_aizu_tests/trees/lca_all_methods_lib_checker.test.cpp": "2025-08-03 22:53:52 -0600",
140140
"tests/library_checker_aizu_tests/trees/subtree_isomorphism.test.cpp": "2024-12-15 14:34:10 -0600"
141141
}

library/trees/linear_lca.hpp

Lines changed: 17 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -10,41 +10,35 @@
1010
//! @endcode
1111
//! @time O(n + q)
1212
//! @space O(n)
13+
int lsb(int x) { return x & -x; }
1314
struct linear_lca {
14-
struct node {
15-
int d, label, asc;
16-
};
17-
vector<node> t;
18-
vi head;
15+
int n;
16+
vi d, in, asc, head;
1917
linear_lca(const auto& adj):
20-
t(sz(adj)), head(sz(t) + 1) {
18+
n(sz(adj)), d(n), in(n), asc(n), head(n + 1) {
2119
vector<pii> order;
2220
auto dfs = [&](auto&& self, int v, int p) -> void {
2321
order.emplace_back(v, p);
24-
t[v].label = sz(order);
22+
in[v] = sz(order);
2523
for (int u : adj[v])
2624
if (u != p) {
27-
t[u].d = 1 + t[v].d;
25+
d[u] = 1 + d[v];
2826
self(self, u, v);
29-
head[t[u].label] = v;
30-
if ((t[u].label & -t[u].label) >
31-
(t[v].label & -t[v].label))
32-
t[v].label = t[u].label;
27+
head[in[u]] = v;
28+
if (lsb(in[v]) < lsb(in[u])) in[v] = in[u];
3329
}
3430
};
35-
rep(i, 0, sz(t)) if (t[i].d == 0) dfs(dfs, i, i);
36-
for (auto [v, p] : order)
37-
t[v].asc = t[p].asc | (t[v].label & -t[v].label);
31+
dfs(dfs, 0, 0);
32+
for (auto [v, p] : order) asc[v] = asc[p] | lsb(in[v]);
3833
}
3934
int lca(int u, int v) {
40-
if (unsigned j = t[u].label ^ t[v].label; j) {
41-
j = t[u].asc & t[v].asc & -bit_floor(j);
42-
if (unsigned k = t[u].asc ^ j; k)
43-
k = bit_floor(k), u = head[(t[u].label & -k) | k];
44-
if (unsigned k = t[v].asc ^ j; k)
45-
k = bit_floor(k), v = head[(t[v].label & -k) | k];
35+
if (unsigned j = in[u] ^ in[v]; j) {
36+
j = asc[u] & asc[v] & -bit_floor(j);
37+
if (unsigned k = asc[u] ^ j; k)
38+
k = bit_floor(k), u = head[(in[u] & -k) | k];
39+
if (unsigned k = asc[v] ^ j; k)
40+
k = bit_floor(k), v = head[(in[v] & -k) | k];
4641
}
47-
return t[u].d < t[v].d ? u : v;
42+
return d[u] < d[v] ? u : v;
4843
}
49-
#include "extra_members/dist_edges.hpp"
5044
};

tests/library_checker_aizu_tests/handmade_tests/lca_ladder_forest.test.cpp

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,8 @@
66
#include "../../../library/monotonic_stack/monotonic_stack.hpp"
77
#include "../../../library/trees/tree_lift/tree_lift.hpp"
88
#include "../../../library/trees/lca_rmq/lca_rmq.hpp"
9-
#include "../../../library/trees/linear_lca.hpp"
109
#include "../../../library/trees/ladder_decomposition/ladder_decomposition.hpp"
1110
#include "../../../library/trees/ladder_decomposition/linear_kth_par.hpp"
12-
#include "../../../library/trees/linear_kth_path.hpp"
1311
int main() {
1412
cin.tie(0)->sync_with_stdio(0);
1513
for (int n = 1; n <= 100; n++) {
@@ -26,31 +24,20 @@ int main() {
2624
}
2725
tree_lift tl(adj);
2826
LCA lc(adj);
29-
linear_lca lin_lca(adj);
3027
ladder lad(adj);
31-
linear_kth_path lin_kth_path(adj);
3228
for (int i = 0; i < 100; i++) {
3329
int u = rnd<int>(0, n - 1);
3430
int v = rnd<int>(0, n - 1);
3531
if (u == v || !dsu.same_set(u, v)) continue;
3632
auto lca_1 = tl.lca(u, v);
3733
auto lca_2 = lc.lca(u, v);
38-
auto lca_3 = lin_lca.lca(u, v);
3934
assert(lca_1 == lca_2);
40-
assert(lca_1 == lca_3);
4135
assert(tl.dist_edges(u, v) == lc.dist_edges(u, v));
42-
assert(
43-
tl.dist_edges(u, v) == lin_lca.dist_edges(u, v));
4436
assert(
4537
tl.kth_path(u, v, 1) == lc.next_on_path(u, v));
46-
assert(lin_kth_path.kth_path(u, v, 1) ==
47-
lc.next_on_path(u, v));
4838
if (tl.t[u].d > tl.t[v].d) swap(u, v);
4939
auto res = tl.kth_par(v, tl.t[v].d - tl.t[u].d);
5040
assert(res == lad.kth_par(v, tl.t[v].d - tl.t[u].d));
51-
assert(res ==
52-
lin_kth_path.lin_kp.kth_par(v,
53-
tl.t[v].d - tl.t[u].d));
5441
assert((u == res) == lc.in_subtree(u, v));
5542
}
5643
}

0 commit comments

Comments
 (0)