|
4 | 4 | //! https://youtu.be/0rCFkuQS968 |
5 | 5 | //! @code |
6 | 6 | //! ladder ld(g); |
| 7 | +//! ld.kth_par(u, k); // kth parent of u |
| 8 | +//! ld.kth_par(u, 0); // u |
| 9 | +//! ld.kth_par(u, 1); // p[u] |
7 | 10 | //! // KACTL functions |
8 | 11 | //! int kth_par = jmp(ld.jmp, u, k); |
9 | 12 | //! int curr_lca = lca(ld.jmp, ld.d, u, v); |
10 | 13 | //! @endcode |
11 | 14 | struct ladder { |
12 | 15 | int n; |
13 | | - vi d, p, leaf, idx, lad; |
| 16 | + vi d, p, idx, l; |
14 | 17 | vector<vi> jmp; |
15 | 18 | //! @param g forest (rooted or unrooted) |
16 | 19 | //! @time O(n log n) |
17 | 20 | //! @space O(n log n) for jmp. Everything else is O(n) |
18 | 21 | ladder(const auto& g): |
19 | | - n(sz(g)), d(n), p(n), leaf(n), idx(n), lad(2 * n) { |
20 | | - auto dfs = [&](auto dfs, int u) -> void { |
21 | | - leaf[u] = u; |
| 22 | + n(sz(g)), d(n), p(n), idx(n), l(2 * n) { |
| 23 | + int i = 0; |
| 24 | + vi s(n); |
| 25 | + auto dfs = [&](auto dfs, int u) -> vi { |
| 26 | + vi path; |
| 27 | + s[d[u]] = u; |
22 | 28 | for (int v : g[u]) |
23 | 29 | if (v != p[u]) { |
24 | 30 | d[v] = d[p[v] = u] + 1; |
25 | | - dfs(dfs, v); |
26 | | - if (d[leaf[u]] < d[leaf[v]]) leaf[u] = leaf[v]; |
| 31 | + vi x = dfs(dfs, v); |
| 32 | + if (sz(x) > sz(path)) swap(x, path); |
| 33 | + for (int y : x) idx[y] = i; |
| 34 | + for (int y : x) l[i++] = y; |
| 35 | + rep(j, 0, min(sz(x), d[v])) l[i++] = s[d[u] - j]; |
27 | 36 | } |
| 37 | + path.push_back(u); |
| 38 | + return path; |
28 | 39 | }; |
29 | | - dfs(dfs, 0); |
30 | | - int pos = 0; |
31 | | - rep(i, 0, n) if (p[i] == i || leaf[p[i]] != leaf[i]) { |
32 | | - int l = leaf[i]; |
33 | | - int len = min((d[l] - d[i]) * 2, d[l] + 1); |
34 | | - idx[l] = pos; |
35 | | - for (; len--; l = p[l]) lad[pos++] = l; |
36 | | - } |
| 40 | + vi x = dfs(dfs, 0); |
| 41 | + for (int y : x) idx[y] = i; |
| 42 | + for (int y : x) l[i++] = y; |
37 | 43 | jmp = treeJump(p); |
38 | 44 | } |
39 | | - //! @param u query node |
40 | | - //! @param k number of edges |
41 | | - //! @returns a node k edges up from u. With k=1, this |
42 | | - //! returns u's parent. |
43 | | - //! @time O(1) |
44 | | - //! @space O(1) |
45 | 45 | int kth_par(int u, int k) { |
46 | 46 | assert(0 <= k && k <= d[u]); |
47 | 47 | if (k == 0) return u; |
48 | 48 | int bit = __lg(k); |
49 | 49 | u = jmp[bit][u], k -= (1 << bit); |
50 | | - int l = idx[leaf[u]] + d[leaf[u]] - d[u]; |
51 | | - assert(lad[l] == u); |
52 | | - // subarray [l, l+k] of lad corresponds to the rest |
| 50 | + int i = idx[u], j = i + d[l[i]] - d[u]; |
| 51 | + assert(l[j] == u); |
| 52 | + // subarray [j, j+k] of l corresponds to the rest |
53 | 53 | // of the jump |
54 | | - return lad[l + k]; |
| 54 | + return l[j + k]; |
55 | 55 | } |
56 | 56 | }; |
0 commit comments