Skip to content

Commit d3d4c46

Browse files
committed
add changes
1 parent f12260f commit d3d4c46

File tree

2 files changed

+56
-55
lines changed

2 files changed

+56
-55
lines changed

library/trees/ladder_decomposition/linear_kth_par.hpp

Lines changed: 40 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -7,62 +7,53 @@
77
//! }
88
//! vector<basic_string<int>> adj(n);
99
//! 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
1112
//! @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;
2219
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++;
3127
};
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]);
3632
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]);
4338
}
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);
4547
};
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);
5449
}
5550
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]];
6758
}
6859
};

tests/library_checker_aizu_tests/trees/kth_path_linear.test.cpp

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,18 +17,28 @@ int main() {
1717
adj[v].push_back(u);
1818
}
1919
linear_lca lin_lca(adj);
20-
linear_kth_par lin_kth_par(adj);
20+
linear_kth_par<2> lin_kp_2(adj);
21+
linear_kth_par<3> lin_kp_3(adj);
22+
linear_kth_par<4> lin_kp_4(adj);
23+
linear_kth_par<5> lin_kp_5(adj);
2124
LCA lc(adj);
2225
compress_tree_asserts(adj, lc);
26+
auto get_kth_par = [&](int v, int k) -> int {
27+
int res = lin_kp_2.kth_par(v, k);
28+
assert(res == lin_kp_3.kth_par(v, k));
29+
assert(res == lin_kp_4.kth_par(v, k));
30+
assert(res == lin_kp_5.kth_par(v, k));
31+
return res;
32+
};
2333
while (q--) {
2434
int u, v, k;
2535
cin >> u >> v >> k;
26-
int lca_d = lin_kth_par.t[lin_lca.lca(u, v)].d;
27-
int u_lca = lin_kth_par.t[u].d - lca_d;
28-
int v_lca = lin_kth_par.t[v].d - lca_d;
29-
if (k <= u_lca) cout << lin_kth_par.kth_par(u, k) << '\n';
36+
int lca_d = lin_kp_2.d[lin_lca.lca(u, v)];
37+
int u_lca = lin_kp_2.d[u] - lca_d;
38+
int v_lca = lin_kp_2.d[v] - lca_d;
39+
if (k <= u_lca) cout << get_kth_par(u, k) << '\n';
3040
else if (k <= u_lca + v_lca)
31-
cout << lin_kth_par.kth_par(v, u_lca + v_lca - k) << '\n';
41+
cout << get_kth_par(v, u_lca + v_lca - k) << '\n';
3242
else cout << -1 << '\n';
3343
}
3444
}

0 commit comments

Comments
 (0)