Skip to content

Commit 3c6c548

Browse files
committed
adding new kth par alg
1 parent 4603cd9 commit 3c6c548

5 files changed

Lines changed: 145 additions & 23 deletions

File tree

library/trees/uncommon/ladder_decomposition.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@ struct ladder {
3030
if (sz(x) > sz(path)) swap(x, path);
3131
for (int y : x) idx[y] = i;
3232
for (int y : x) lad[i++] = y;
33-
rep(j, 0, min<int>(sz(x), d[v]))
34-
lad[i++] = st[d[u] - j];
33+
rep(k, 0, min<int>(sz(x), d[v]))
34+
lad[i++] = st[d[u] - k];
3535
}
3636
path.push_back(u);
3737
return path;
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
#pragma once
2+
//! https://link.springer.com/chapter/10.1007/978-3-032-29003-8_29
3+
//! @code
4+
//! vector<basic_string<int>> g(n);
5+
//! linear_kth_par kp(g);
6+
//! kp.kth_par(v, k); // k edges up from v
7+
//! kp.kth_par(v, 1); // v's parent
8+
//! @endcode
9+
//! @time O(n + q)
10+
//! @space O(n)
11+
struct linear_kth_par {
12+
int n;
13+
vi d, et_i, et_d, idx, lad;
14+
vector<basic_string<int>> jmp;
15+
linear_kth_par(const auto& g):
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+
vi st(n);
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++;
25+
};
26+
auto dfs = [&](auto dfs, int u, int p) -> vi {
27+
vi path;
28+
st[d[u]] = u;
29+
calc(u);
30+
for (int v : g[u])
31+
if (v != p) {
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];
40+
}
41+
path.push_back(u);
42+
return path;
43+
};
44+
vi x = dfs(dfs, 0, 0);
45+
for (int y : x) idx[y] = i;
46+
for (int y : x) lad[i++] = y;
47+
}
48+
int kth_par(int u, int k) {
49+
assert(0 <= k && k <= d[u]);
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];
55+
}
56+
};
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
#define PROBLEM \
2+
"https://onlinejudge.u-aizu.ac.jp/problems/ITP1_1_A"
3+
#include "../template.hpp"
4+
#include "../../../library/contest/random.hpp"
5+
#include "../../../library/trees/uncommon/hagerup_kth_par.hpp"
6+
#include "../../../library/trees/uncommon/linear_kth_par.hpp"
7+
int main() {
8+
for (int n = 1; n <= 600; n++) {
9+
for (int param = 1; param < 20; param++) {
10+
vector<int> par(n);
11+
vector<vector<int>> adj(n);
12+
for (int i = 1; i < n; i++) {
13+
if (param == 19) par[i] = rnd(0, i - 1);
14+
else par[i] = rnd(max(0, i - param), i - 1);
15+
adj[par[i]].push_back(i);
16+
adj[i].push_back(par[i]);
17+
}
18+
hagerup<2> hagerup_kth_par(adj);
19+
linear_kth_par lin_kth_par(adj);
20+
for (int i = 0; i < n; i++) {
21+
for (int k = 0, kth_parent_naive = i;
22+
k <= hagerup_kth_par.d[i];
23+
k++, kth_parent_naive = par[kth_parent_naive]) {
24+
assert(kth_parent_naive ==
25+
hagerup_kth_par.kth_par(i, k));
26+
assert(
27+
kth_parent_naive == lin_kth_par.kth_par(i, k));
28+
}
29+
}
30+
}
31+
}
32+
cout << "Hello World\n";
33+
return 0;
34+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
#define PROBLEM \
2+
"https://judge.yosupo.jp/problem/jump_on_tree"
3+
#include "../template.hpp"
4+
#include "../../../library/trees/linear_lca.hpp"
5+
#include "../../../library/trees/uncommon/hagerup_kth_par.hpp"
6+
#include "../../../library/trees/lca_rmq.hpp"
7+
#include "../compress_tree_asserts.hpp"
8+
int main() {
9+
cin.tie(0)->sync_with_stdio(0);
10+
int n, q;
11+
cin >> n >> q;
12+
vector<vector<int>> adj(n);
13+
for (int i = 0; i < n - 1; i++) {
14+
int u, v;
15+
cin >> u >> v;
16+
adj[u].push_back(v);
17+
adj[v].push_back(u);
18+
}
19+
linear_lca lin_lca(adj);
20+
hagerup<1> lin_kp_1(adj);
21+
hagerup<2> lin_kp_2(adj);
22+
hagerup<3> lin_kp_3(adj);
23+
hagerup<4> lin_kp_4(adj);
24+
LCA lc(adj);
25+
compress_tree_asserts(adj, lc);
26+
auto get_kth_par = [&](int v, int k) -> int {
27+
int res = lin_kp_1.kth_par(v, k);
28+
assert(res == lin_kp_2.kth_par(v, k));
29+
assert(res == lin_kp_3.kth_par(v, k));
30+
assert(res == lin_kp_4.kth_par(v, k));
31+
return res;
32+
};
33+
while (q--) {
34+
int u, v, k;
35+
cin >> u >> v >> k;
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';
40+
else if (k <= u_lca + v_lca)
41+
cout << get_kth_par(v, u_lca + v_lca - k) << '\n';
42+
else cout << -1 << '\n';
43+
}
44+
}

tests/library_checker_aizu_tests/trees/kth_path_linear.test.cpp

Lines changed: 9 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,7 @@
22
"https://judge.yosupo.jp/problem/jump_on_tree"
33
#include "../template.hpp"
44
#include "../../../library/trees/linear_lca.hpp"
5-
#include "../../../library/trees/uncommon/hagerup_kth_par.hpp"
6-
#include "../../../library/trees/lca_rmq.hpp"
7-
#include "../compress_tree_asserts.hpp"
5+
#include "../../../library/trees/uncommon/linear_kth_par.hpp"
86
int main() {
97
cin.tie(0)->sync_with_stdio(0);
108
int n, q;
@@ -17,28 +15,18 @@ int main() {
1715
adj[v].push_back(u);
1816
}
1917
linear_lca lin_lca(adj);
20-
hagerup<1> lin_kp_1(adj);
21-
hagerup<2> lin_kp_2(adj);
22-
hagerup<3> lin_kp_3(adj);
23-
hagerup<4> lin_kp_4(adj);
24-
LCA lc(adj);
25-
compress_tree_asserts(adj, lc);
26-
auto get_kth_par = [&](int v, int k) -> int {
27-
int res = lin_kp_1.kth_par(v, k);
28-
assert(res == lin_kp_2.kth_par(v, k));
29-
assert(res == lin_kp_3.kth_par(v, k));
30-
assert(res == lin_kp_4.kth_par(v, k));
31-
return res;
32-
};
18+
linear_kth_par lin_kth_par(adj);
3319
while (q--) {
3420
int u, v, k;
3521
cin >> u >> v >> k;
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';
22+
int lca_d = lin_lca.d[lin_lca.lca(u, v)];
23+
int u_lca = lin_lca.d[u] - lca_d;
24+
int v_lca = lin_lca.d[v] - lca_d;
25+
if (k <= u_lca)
26+
cout << lin_kth_par.kth_par(u, k) << '\n';
4027
else if (k <= u_lca + v_lca)
41-
cout << get_kth_par(v, u_lca + v_lca - k) << '\n';
28+
cout << lin_kth_par.kth_par(v, u_lca + v_lca - k)
29+
<< '\n';
4230
else cout << -1 << '\n';
4331
}
4432
}

0 commit comments

Comments
 (0)