|
1 | 1 | #pragma once |
2 | | -//! https://codeforces.com/blog/entry/126580 |
| 2 | +//! https://link.springer.com/chapter/10.1007/978-3-032-29003-8_29 |
3 | 3 | //! @code |
4 | 4 | //! vector<basic_string<int>> g(n); |
5 | 5 | //! linear_kth_par kp(g); |
6 | 6 | //! kp.kth_par(v, k); // k edges up from v |
7 | 7 | //! kp.kth_par(v, 1); // v's parent |
8 | 8 | //! @endcode |
9 | | -//! @time O(n*max((2*K+3)/K,2*K) + q) |
10 | | -//! @space O(n*max((2*K+3)/K,2*K)) |
11 | | -template<int K = 2> struct linear_kth_par { |
| 9 | +//! @time O(n + q) |
| 10 | +//! @space O(n) |
| 11 | +struct linear_kth_par { |
12 | 12 | int n; |
13 | | - vi d, leaf, pos, jmp; |
14 | | - vector<vi> lad; |
| 13 | + vi d, et_i, et_d, idx, lad; |
| 14 | + vector<basic_string<int>> jmp; |
15 | 15 | linear_kth_par(const auto& g): |
16 | | - n(sz(g)), d(n), leaf(n), pos(n), jmp(2 * n), lad(n) { |
17 | | - static_assert(K >= 1); |
18 | | - int t = 1; |
| 16 | + n(sz(g)), d(n), et_i(n), et_d(2 * n), idx(n), |
| 17 | + lad(2 * n), jmp(2 * n) { |
| 18 | + int i = 0, j = 1; |
19 | 19 | vi st(n); |
20 | | - auto calc = [&](int s) { |
21 | | - jmp[t] = st[max(0, s - K * (t & -t))]; |
22 | | - t++; |
| 20 | + auto calc = [&](int u) { |
| 21 | + et_d[et_i[u] = j] = d[u]; |
| 22 | + for (int k = 1; k <= min(j & -j, d[u]); k *= 2) |
| 23 | + jmp[j] += st[d[u] - k]; |
| 24 | + j++; |
23 | 25 | }; |
24 | | - auto dfs = [&](auto dfs, int u, int p) -> void { |
25 | | - int& l = leaf[u] = st[d[u]] = u; |
26 | | - pos[u] = t; |
27 | | - calc(d[u]); |
| 26 | + auto dfs = [&](auto dfs, int u, int p) -> vi { |
| 27 | + vi path; |
| 28 | + st[d[u]] = u; |
| 29 | + calc(u); |
28 | 30 | for (int v : g[u]) |
29 | 31 | if (v != p) { |
30 | | - d[v] = 1 + d[u]; |
31 | | - dfs(dfs, v, u); |
32 | | - if (d[l] < d[leaf[v]]) l = leaf[v]; |
33 | | - calc(d[u]); |
| 32 | + d[v] = d[u] + 1; |
| 33 | + vi x = dfs(dfs, v, u); |
| 34 | + calc(u); |
| 35 | + if (sz(x) > sz(path)) swap(x, path); |
| 36 | + for (int y : x) idx[y] = i; |
| 37 | + for (int y : x) lad[i++] = y; |
| 38 | + rep(k, 0, min<int>(sz(x), d[v])) |
| 39 | + lad[i++] = st[d[u] - k]; |
34 | 40 | } |
35 | | - int s = (d[l] - d[u]) * (2 * K + 3) / K; |
36 | | - s = min(max(s, 2 * K), d[l] + 1); |
37 | | - rep(i, sz(lad[l]), s) lad[l].push_back(st[d[l] - i]); |
| 41 | + path.push_back(u); |
| 42 | + return path; |
38 | 43 | }; |
39 | | - dfs(dfs, 0, 0); |
| 44 | + vi x = dfs(dfs, 0, 0); |
| 45 | + for (int y : x) idx[y] = i; |
| 46 | + for (int y : x) lad[i++] = y; |
40 | 47 | } |
41 | 48 | int kth_par(int u, int k) { |
42 | 49 | assert(0 <= k && k <= d[u]); |
43 | | - int anc_d = d[u] - k; |
44 | | - if (int j = bit_floor(k / (K + 1u))) |
45 | | - u = jmp[(pos[u] & -j) | j]; |
46 | | - return u = leaf[u], lad[u][d[u] - anc_d]; |
| 50 | + if (k == 0) return u; |
| 51 | + int anc_d = d[u] - k, bc = bit_ceil(k + 0u); |
| 52 | + int j = (et_i[u] + bc / 2) & -bc; |
| 53 | + int i = idx[jmp[j].at(__lg(et_d[j] - anc_d))]; |
| 54 | + return lad[i + d[lad[i]] - anc_d]; |
47 | 55 | } |
48 | 56 | }; |
0 commit comments