|
7 | 7 | //! } |
8 | 8 | //! vector<basic_string<int>> adj(n); |
9 | 9 | //! linear_kth_par kp(adj); |
10 | | -//! int kth_par = kp.kth_par(v, k); |
| 10 | +//! kp.kth_par(v, k); // k edges up from v |
| 11 | +//! kp.kth_par(v, 1); // v's parent |
11 | 12 | //! @endcode |
12 | | -//! kth_par = a node k edges up from v |
13 | | -//! @time O(n + q) |
14 | | -//! @space O(n) |
15 | | -struct linear_kth_par { |
16 | | - struct node { |
17 | | - int d, p = -1, dl, idx_j; |
18 | | - basic_string<int> lad; |
19 | | - }; |
20 | | - vector<node> t; |
21 | | - vector<pii> j; |
| 13 | +//! @time O(n*(2*KAPPA+1)/(KAPPA-1) + n*2*(KAPPA-1) + q) |
| 14 | +//! @space O(n*(2*KAPPA+1)/(KAPPA-1) + n*2*(KAPPA-1)) |
| 15 | +template<int KAPPA = 3> struct linear_kth_par { |
| 16 | + int n; |
| 17 | + vi d, leaf, pos, jmp; |
| 18 | + vector<basic_string<int>> lad; |
22 | 19 | linear_kth_par(const auto& adj): |
23 | | - t(sz(adj)), j(2 * sz(t)) { |
24 | | - vi st; |
25 | | - int pos = 1; |
26 | | - auto add_j = [&]() -> void { |
27 | | - j[pos] = { |
28 | | - st[max<int>(0, sz(st) - 1 - 2 * (pos & -pos))], |
29 | | - st[max<int>(0, sz(st) - 1 - 4 * (pos & -pos))]}; |
30 | | - pos++; |
| 20 | + n(sz(adj)), d(n), leaf(n), pos(n), jmp(2 * n), lad(n) { |
| 21 | + static_assert(KAPPA >= 2); |
| 22 | + int t = 1; |
| 23 | + vi st(n); |
| 24 | + auto calc = [&](int siz) { |
| 25 | + jmp[t] = st[max(0, siz - (KAPPA - 1) * (t & -t))]; |
| 26 | + t++; |
31 | 27 | }; |
32 | | - auto dfs = [&](auto&& self, int v) -> void { |
33 | | - st.push_back(v); |
34 | | - t[v].idx_j = pos, t[v].dl = v; |
35 | | - add_j(); |
| 28 | + auto dfs = [&](auto&& self, int v, int p) -> void { |
| 29 | + st[d[v]] = leaf[v] = v; |
| 30 | + pos[v] = t; |
| 31 | + calc(d[v]); |
36 | 32 | for (int u : adj[v]) |
37 | | - if (u != t[v].p) { |
38 | | - t[u].d = t[t[u].p = v].d + 1; |
39 | | - self(self, u); |
40 | | - if (t[t[u].dl].d > t[t[v].dl].d) |
41 | | - t[v].dl = t[u].dl; |
42 | | - add_j(); |
| 33 | + if (u != p) { |
| 34 | + d[u] = 1 + d[v]; |
| 35 | + self(self, u, v); |
| 36 | + if (d[leaf[v]] < d[leaf[u]]) leaf[v] = leaf[u]; |
| 37 | + calc(d[v]); |
43 | 38 | } |
44 | | - st.pop_back(); |
| 39 | + // TODO golf this further |
| 40 | + int len = (d[leaf[v]] - d[v]) * (2 * KAPPA + 1) / |
| 41 | + (KAPPA - 1); |
| 42 | + len = max(len, 2 * (KAPPA - 1)); |
| 43 | + int i = d[leaf[v]] - sz(lad[leaf[v]]); |
| 44 | + while (i && sz(lad[leaf[v]]) < len) |
| 45 | + lad[leaf[v]] += st[i--]; |
| 46 | + assert(lad[leaf[v]].back() > 0); |
45 | 47 | }; |
46 | | - rep(i, 0, sz(t)) { |
47 | | - if (t[i].p == -1) dfs(dfs, i); |
48 | | - if (t[i].p == -1 || t[t[i].p].dl != t[i].dl) { |
49 | | - int v = t[i].dl, len = (t[v].d - t[i].d) * 2; |
50 | | - auto& lad = t[v].lad; |
51 | | - for (; v != -1 && len--; v = t[v].p) lad += v; |
52 | | - } |
53 | | - } |
| 48 | + dfs(dfs, 0, 0); |
54 | 49 | } |
55 | 50 | int kth_par(int v, int k) { |
56 | | - assert(0 <= k && k <= t[v].d); |
57 | | - switch (k) { |
58 | | - case 0: return v; |
59 | | - case 1: return t[v].p; |
60 | | - case 2: return t[t[v].p].p; |
61 | | - default: |
62 | | - int i = bit_floor(unsigned(k / 3)); |
63 | | - auto [j1, j2] = j[(t[v].idx_j & -i) | i]; |
64 | | - int leaf = t[t[v].d - t[j2].d <= k ? j2 : j1].dl; |
65 | | - return t[leaf].lad[k + t[leaf].d - t[v].d]; |
66 | | - } |
| 51 | + assert(0 <= k && k <= d[v]); |
| 52 | + int j = v; |
| 53 | + if (unsigned b = k / KAPPA; b) |
| 54 | + b = bit_floor(b), j = jmp[(pos[v] & -b) | b]; |
| 55 | + // TODO array index out of bounds goes uncaught here |
| 56 | + // because of basic_string |
| 57 | + return j = leaf[j], lad[j][k + d[j] - d[v]]; |
67 | 58 | } |
68 | 59 | }; |
0 commit comments