static_tree.hpp
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | #pragma once | ||
| 2 | |||
| 3 | #include "yc.hpp" | ||
| 4 | #include "rmq.hpp" | ||
| 5 | |||
| 6 | struct static_forest_t { | ||
| 7 | int N; | ||
| 8 | |||
| 9 | private: | ||
| 10 | // original label to preorder | ||
| 11 | std::vector<int> idx; | ||
| 12 | |||
| 13 | // all keys/values are by preorder relabelling | ||
| 14 | std::vector<int> preorder; | ||
| 15 | std::vector<int> depth; | ||
| 16 | std::vector<int> par; | ||
| 17 | std::vector<int> sz; | ||
| 18 | std::vector<int> heavy_par; | ||
| 19 | std::vector<int> heavy_dist; | ||
| 20 | |||
| 21 | std::vector<int> depth_val_to_idx; | ||
| 22 | RangeMinQuery<int> depth_val_rmq; | ||
| 23 | |||
| 24 | public: | ||
| 25 | |||
| 26 | ✗ | static_forest_t() : N(0) {} | |
| 27 |
1/2✗ Branch 2 → 3 not taken.
✓ Branch 2 → 4 taken 25 times.
|
25 | static_forest_t(const std::vector<std::vector<int>>& adj, const std::vector<int>& roots = {}) : |
| 28 | 25 | N(int(adj.size())), | |
| 29 |
1/1✓ Branch 5 → 6 taken 25 times.
|
25 | idx(N, -1), |
| 30 |
2/3✓ Branch 5 → 6 taken 25 times.
✓ Branch 6 → 7 taken 25 times.
✗ Branch 9 → 10 not taken.
|
25 | preorder(N, -1), |
| 31 |
2/3✓ Branch 6 → 7 taken 25 times.
✓ Branch 7 → 8 taken 25 times.
✗ Branch 13 → 14 not taken.
|
25 | depth(N, -1), |
| 32 |
2/3✓ Branch 7 → 8 taken 25 times.
✓ Branch 8 → 9 taken 25 times.
✗ Branch 17 → 18 not taken.
|
25 | par(N, -1), |
| 33 |
2/3✓ Branch 8 → 9 taken 25 times.
✓ Branch 9 → 10 taken 25 times.
✗ Branch 21 → 22 not taken.
|
25 | sz(N, -1), |
| 34 |
2/3✓ Branch 9 → 10 taken 25 times.
✓ Branch 10 → 11 taken 25 times.
✗ Branch 25 → 26 not taken.
|
25 | heavy_par(N, -1), |
| 35 |
2/3✓ Branch 10 → 11 taken 25 times.
✓ Branch 11 → 12 taken 25 times.
✗ Branch 29 → 30 not taken.
|
25 | heavy_dist(N, -1), |
| 36 |
2/3✓ Branch 11 → 12 taken 25 times.
✓ Branch 12 → 13 taken 25 times.
✗ Branch 33 → 34 not taken.
|
25 | depth_val_to_idx(N, -1) |
| 37 | { | ||
| 38 | 25 | { | |
| 39 | 25 | int nxt_idx = 0; | |
| 40 |
2/3✓ Branch 12 → 13 taken 25 times.
✓ Branch 13 → 14 taken 25 times.
✗ Branch 38 → 39 not taken.
|
25 | std::vector<int> depth_freq(N, 0); |
| 41 |
2/3✓ Branch 13 → 14 taken 25 times.
✓ Branch 14 → 15 taken 25 times.
✗ Branch 42 → 43 not taken.
|
25 | std::vector<int> depth_val(N, -1); |
| 42 |
2/4✓ Branch 14 → 15 taken 25 times.
✓ Branch 15 → 18 taken 25 times.
✗ Branch 15 → 22 not taken.
✗ Branch 46 → 47 not taken.
|
25 | std::vector<int> heavy_child(N, -1); |
| 43 | 50 | auto build_one_tree = [&](int rt) -> void { | |
| 44 |
0/1✗ Branch 2 → 3 not taken.
|
10224977 | std::y_combinator([&](auto self, int cur, int prv) -> int { |
| 45 | 10224927 | int cur_sz = 1; | |
| 46 | 10224927 | int cur_heavy = -1; | |
| 47 | 10224927 | int cur_heavy_weight = 0; | |
| 48 |
2/4✓ Branch 10 → 3 taken 20449804 times.
✓ Branch 10 → 11 taken 10224927 times.
✗ Branch 22 → 5 not taken.
✗ Branch 22 → 23 not taken.
|
30674731 | for (int nxt : adj[cur]) { |
| 49 |
2/4✓ Branch 3 → 4 taken 10224902 times.
✓ Branch 3 → 5 taken 10224902 times.
✗ Branch 7 → 8 not taken.
✗ Branch 7 → 9 not taken.
|
20449804 | if (nxt == prv) continue; |
| 50 |
0/1✗ Branch 9 → 10 not taken.
|
10224902 | int n_sz = self(nxt, cur); |
| 51 |
2/4✓ Branch 6 → 7 taken 7921998 times.
✓ Branch 6 → 8 taken 2302904 times.
✗ Branch 10 → 11 not taken.
✗ Branch 10 → 12 not taken.
|
10224902 | if (n_sz > cur_heavy_weight) { |
| 52 | 7921998 | cur_heavy = nxt; | |
| 53 | 7921998 | cur_heavy_weight = n_sz; | |
| 54 | } | ||
| 55 | 10224902 | cur_sz += n_sz; | |
| 56 | } | ||
| 57 | 10224927 | heavy_child[cur] = cur_heavy; | |
| 58 | 10224927 | return cur_sz; | |
| 59 |
0/1✗ Branch 3 → 4 not taken.
|
25 | })(rt, -1); |
| 60 | 25 | assert(idx[rt] == -1); | |
| 61 |
0/1✗ Branch 7 → 8 not taken.
|
10224977 | std::y_combinator([&](auto&& self, int cur, int prv, int par_idx, int d, bool is_heavy_root) -> void { |
| 62 |
2/2✓ Branch 2 → 3 taken 10224902 times.
✓ Branch 2 → 5 taken 25 times.
|
10224927 | int cur_idx = idx[cur] = nxt_idx++; |
| 63 | 10224927 | preorder[cur_idx] = cur; | |
| 64 | 10224927 | par[cur_idx] = par_idx; | |
| 65 | 10224927 | depth[cur_idx] = d; | |
| 66 | 10224927 | depth_val[cur_idx] = ++depth_freq[d]; | |
| 67 | 17769323 | assert(is_heavy_root == (par_idx == -1 || cur_idx != par_idx + 1)); | |
| 68 |
2/4✓ Branch 7 → 8 taken 2680531 times.
✓ Branch 7 → 9 taken 7544396 times.
✗ Branch 14 → 15 not taken.
✗ Branch 14 → 18 not taken.
|
10224927 | if (is_heavy_root) { |
| 69 | 2680531 | heavy_par[cur_idx] = par_idx; | |
| 70 | 2680531 | heavy_dist[cur_idx] = 1; | |
| 71 | } else { | ||
| 72 | 7544396 | assert(par_idx == cur_idx - 1); | |
| 73 | 7544396 | heavy_par[cur_idx] = heavy_par[cur_idx - 1]; | |
| 74 | 7544396 | heavy_dist[cur_idx] = heavy_dist[cur_idx - 1] + 1; | |
| 75 | } | ||
| 76 |
2/4✓ Branch 12 → 13 taken 7544396 times.
✓ Branch 12 → 15 taken 2680531 times.
✗ Branch 26 → 27 not taken.
✗ Branch 26 → 30 not taken.
|
10224927 | if (heavy_child[cur] != -1) { |
| 77 | 7544396 | int nxt = heavy_child[cur]; | |
| 78 |
0/1✗ Branch 28 → 29 not taken.
|
7544396 | self(nxt, cur, cur_idx, d+1, false); |
| 79 | } | ||
| 80 |
2/4✓ Branch 23 → 16 taken 20449804 times.
✓ Branch 23 → 24 taken 10224927 times.
✗ Branch 51 → 33 not taken.
✗ Branch 51 → 52 not taken.
|
30674731 | for (int nxt : adj[cur]) { |
| 81 |
2/4✓ Branch 16 → 17 taken 10224902 times.
✓ Branch 16 → 18 taken 10224902 times.
✗ Branch 35 → 36 not taken.
✗ Branch 35 → 37 not taken.
|
20449804 | if (nxt == prv) continue; |
| 82 |
2/4✓ Branch 18 → 19 taken 7544396 times.
✓ Branch 18 → 20 taken 2680506 times.
✗ Branch 38 → 39 not taken.
✗ Branch 38 → 40 not taken.
|
10224902 | if (nxt == heavy_child[cur]) continue; |
| 83 |
0/1✗ Branch 40 → 41 not taken.
|
2680506 | self(nxt, cur, cur_idx, d+1, true); |
| 84 | } | ||
| 85 | 10224927 | sz[cur_idx] = nxt_idx - cur_idx; | |
| 86 |
0/1✗ Branch 8 → 9 not taken.
|
25 | })(rt, -1, -1, 0, true); |
| 87 | 50 | }; | |
| 88 |
1/4✓ Branch 15 → 18 taken 25 times.
✗ Branch 15 → 22 not taken.
✗ Branch 49 → 50 not taken.
✗ Branch 49 → 66 not taken.
|
25 | if (!roots.empty()) { |
| 89 |
3/6✓ Branch 16 → 17 taken 25 times.
✓ Branch 18 → 16 taken 25 times.
✓ Branch 18 → 26 taken 25 times.
✗ Branch 54 → 55 not taken.
✗ Branch 64 → 52 not taken.
✗ Branch 64 → 65 not taken.
|
50 | for (int r : roots) build_one_tree(r); |
| 90 | } else { | ||
| 91 | ✗ | for (int rt = 0; rt < N; rt++) { | |
| 92 | ✗ | if (idx[rt] == -1) { | |
| 93 | ✗ | build_one_tree(rt); | |
| 94 | } | ||
| 95 | } | ||
| 96 | } | ||
| 97 |
2/4✓ Branch 27 → 23 taken 10224927 times.
✓ Branch 27 → 29 taken 25 times.
✗ Branch 77 → 73 not taken.
✗ Branch 77 → 78 not taken.
|
10224952 | for (int i = 0; i < N; i++) { |
| 98 | 10224927 | assert(idx[i] != -1); | |
| 99 | } | ||
| 100 |
2/4✓ Branch 29 → 28 taken 10224902 times.
✓ Branch 29 → 33 taken 25 times.
✗ Branch 82 → 79 not taken.
✗ Branch 82 → 83 not taken.
|
10224927 | for (int i = 1; i < N; i++) { |
| 101 | 10224902 | depth_freq[i] += depth_freq[i-1]; | |
| 102 | } | ||
| 103 |
2/4✓ Branch 33 → 30 taken 10224927 times.
✓ Branch 33 → 34 taken 25 times.
✗ Branch 95 → 84 not taken.
✗ Branch 95 → 96 not taken.
|
10224952 | for (int i = 0; i < N; i++) { |
| 104 |
1/2✗ Branch 30 → 31 not taken.
✓ Branch 30 → 32 taken 10224927 times.
|
10224927 | depth_val[i] = depth_freq[depth[i]] - depth_val[i]; |
| 105 | 10224927 | assert(depth_val_to_idx[depth_val[i]] == -1); | |
| 106 | 10224927 | depth_val_to_idx[depth_val[i]] = i; | |
| 107 | } | ||
| 108 |
1/2✓ Branch 34 → 35 taken 25 times.
✗ Branch 96 → 97 not taken.
|
25 | depth_val_rmq = RangeMinQuery<int>(depth_val); |
| 109 | 25 | } | |
| 110 | 25 | } | |
| 111 | |||
| 112 | ✗ | int dist(int a, int b) const { | |
| 113 | ✗ | if (a == b) return 0; | |
| 114 | ✗ | a = idx[a], b = idx[b]; | |
| 115 | ✗ | if (a > b) std::swap(a, b); | |
| 116 | ✗ | int o = depth_val_to_idx[depth_val_rmq.query(a+1, b)]; | |
| 117 | ✗ | return depth[a] + depth[b] - 2 * (depth[o] - 1); | |
| 118 | } | ||
| 119 | |||
| 120 | 9662271 | int lca(int a, int b) const { | |
| 121 |
1/3✓ Branch 2 → 3 taken 9662271 times.
✗ Branch 2 → 4 not taken.
✗ Branch 2 → 7 not taken.
|
9662271 | if (a == b) return a; |
| 122 |
2/2✓ Branch 3 → 4 taken 4222685 times.
✓ Branch 3 → 5 taken 5439586 times.
|
9662271 | a = idx[a], b = idx[b]; |
| 123 |
2/4✓ Branch 3 → 4 taken 4222685 times.
✓ Branch 3 → 5 taken 5439586 times.
✗ Branch 6 → 7 not taken.
✗ Branch 6 → 8 not taken.
|
9662271 | if (a > b) std::swap(a, b); |
| 124 | 9662271 | int o = depth_val_to_idx[depth_val_rmq.query(a+1, b)]; | |
| 125 | 9662271 | return preorder[par[o]]; | |
| 126 | } | ||
| 127 | |||
| 128 | // query which subtree of a contains b; b must be inside a | ||
| 129 | // returns -1 if a == b | ||
| 130 | ✗ | int get_subtree(int a, int b) const { | |
| 131 | ✗ | if (a == b) return -1; | |
| 132 | ✗ | a = idx[a], b = idx[b]; | |
| 133 | ✗ | assert(a < b && b < a + sz[a]); | |
| 134 | ✗ | return preorder[depth_val_to_idx[depth_val_rmq.query(a+1, b)]]; | |
| 135 | } | ||
| 136 | |||
| 137 | // next from a to b, a and b must be in the same tree | ||
| 138 | ✗ | int get_next(int a, int b) const { | |
| 139 | ✗ | if (a == b) return -1; | |
| 140 | ✗ | a = idx[a], b = idx[b]; | |
| 141 | ✗ | if (a < b && b < a + sz[a]) { | |
| 142 | ✗ | return preorder[depth_val_to_idx[depth_val_rmq.query(a+1, b)]]; | |
| 143 | } else { | ||
| 144 | ✗ | return preorder[par[a]]; | |
| 145 | } | ||
| 146 | } | ||
| 147 | |||
| 148 | ✗ | int get_ancestor(int a, int k) const { | |
| 149 | ✗ | assert(k >= 0); | |
| 150 | ✗ | a = idx[a]; | |
| 151 | ✗ | if (k > depth[a]) return -1; | |
| 152 | ✗ | while (a != -1 && k > 0) { | |
| 153 | ✗ | if (k >= heavy_dist[a]) { | |
| 154 | ✗ | k -= heavy_dist[a]; | |
| 155 | ✗ | assert(heavy_par[a] <= a - heavy_dist[a]); | |
| 156 | ✗ | a = heavy_par[a]; | |
| 157 | } else { | ||
| 158 | ✗ | a -= k; | |
| 159 | ✗ | k = 0; | |
| 160 | } | ||
| 161 | } | ||
| 162 | ✗ | return preorder[a]; | |
| 163 | } | ||
| 164 | |||
| 165 | ✗ | int get_depth(int a) const { return depth[idx[a]]; } | |
| 166 | ✗ | int get_sz(int a) const { return sz[idx[a]]; } | |
| 167 | ✗ | std::array<int, 2> get_range(int a) const { return {idx[a], idx[a] + sz[idx[a]]}; } | |
| 168 | ✗ | bool is_ancestor(int a, int b) { return idx[a] <= idx[b] && idx[b] < idx[a] + sz[idx[a]]; } | |
| 169 | }; | ||
| 170 |