|
10 | 10 | //! @endcode |
11 | 11 | //! @time O(n + q) |
12 | 12 | //! @space O(n) |
| 13 | +int lsb(int x) { return x & -x; } |
13 | 14 | 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; |
19 | 17 | 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) { |
21 | 19 | vector<pii> order; |
22 | 20 | auto dfs = [&](auto&& self, int v, int p) -> void { |
23 | 21 | order.emplace_back(v, p); |
24 | | - t[v].label = sz(order); |
| 22 | + in[v] = sz(order); |
25 | 23 | for (int u : adj[v]) |
26 | 24 | if (u != p) { |
27 | | - t[u].d = 1 + t[v].d; |
| 25 | + d[u] = 1 + d[v]; |
28 | 26 | 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]; |
33 | 29 | } |
34 | 30 | }; |
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]); |
38 | 33 | } |
39 | 34 | 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]; |
46 | 41 | } |
47 | | - return t[u].d < t[v].d ? u : v; |
| 42 | + return d[u] < d[v] ? u : v; |
48 | 43 | } |
49 | | -#include "extra_members/dist_edges.hpp" |
50 | 44 | }; |
0 commit comments