From 50720686e0d2362eac3c146209b47e4f9a5ee349 Mon Sep 17 00:00:00 2001 From: Luke Videckis Date: Tue, 22 Apr 2025 19:30:56 -0600 Subject: [PATCH 1/7] adding progress --- library/trees/edge_cd.hpp | 17 +++++----- .../edge_cd_asserts.hpp | 32 ++++++++++++++++--- 2 files changed, 36 insertions(+), 13 deletions(-) diff --git a/library/trees/edge_cd.hpp b/library/trees/edge_cd.hpp index 3447ecfc..eb50f86f 100644 --- a/library/trees/edge_cd.hpp +++ b/library/trees/edge_cd.hpp @@ -19,14 +19,14 @@ //! }); //! @endcode //! handle single-edge-paths separately -//! @time O(n log1.5 n) +//! @time O(n logφ n) //! @space O(n) -template struct edge_cd { +template +struct edge_cd { vector adj; F f; vi sub_sz; - edge_cd(const vector& adj, F f): - adj(adj), f(f), sub_sz(sz(adj)) { + edge_cd(const vector& adj, F f) : adj(adj), f(f), sub_sz(sz(adj)) { dfs(0, sz(adj)); } int find_cent(int v, int p, int siz) { @@ -38,17 +38,16 @@ template struct edge_cd { sub_sz[v] += sub_sz[u]; } if (p == -1) return v; - return 2 * sub_sz[v] >= siz - ? sub_sz[p] = siz - sub_sz[v], - v : -1; + return 2 * sub_sz[v] >= siz ? sub_sz[p] = siz - sub_sz[v], v : -1; } void dfs(int v, int siz) { if (siz <= 2) return; v = find_cent(v, -1, siz); int sum = 0; auto it = partition(all(adj[v]), [&](int u) { - bool ret = 2 * sum + sub_sz[u] < siz - 1 && - 3 * (sum + sub_sz[u]) <= 2 * (siz - 1); + ll b = sum + sub_sz[u]; + ll a = siz - 1 - b; + bool ret = (b * b <= a * (a + b)); if (ret) sum += sub_sz[u]; return ret; }); diff --git a/tests/library_checker_aizu_tests/edge_cd_asserts.hpp b/tests/library_checker_aizu_tests/edge_cd_asserts.hpp index 4a39fbbb..e24c9f7a 100644 --- a/tests/library_checker_aizu_tests/edge_cd_asserts.hpp +++ b/tests/library_checker_aizu_tests/edge_cd_asserts.hpp @@ -1,6 +1,5 @@ #pragma once -void edge_cd_asserts(const vector& adj, int cent, - int split) { +void edge_cd_asserts(const vector& adj, int cent, int split) { assert(0 < split && split < sz(adj[cent])); auto dfs = [&](auto&& self, int u, int p) -> int { int siz = 1; @@ -11,12 +10,37 @@ void edge_cd_asserts(const vector& adj, int cent, int sz_all = dfs(dfs, cent, -1); assert(sz_all >= 3); array cnts = {0, 0}; + array max_cnt = {0, 0}; for (int i = 0; i < sz(adj[cent]); i++) { int sz_subtree = dfs(dfs, adj[cent][i], cent); assert(2 * sz_subtree <= sz_all); cnts[i < split] += sz_subtree; + max_cnt[i < split] = max(max_cnt[i < split], sz_subtree); } assert(cnts[0] + cnts[1] + 1 == sz_all); - for (int i = 0; i < 2; i++) - assert(0 < cnts[i] && cnts[i] <= 2 * cnts[!i]); + + if (sz_all == 4) return; + + // a is the number of edges in the smaller edge set + // b is the number of edges in the larger edge set + // so we know 1/2 <= b/(a+b) + // returns true iff b/(a+b) <= 1/phi + auto is_balanced = [&](ll a, ll b) -> bool { + assert(a <= b); + return b * b <= a * (a + b); + }; + + if (cnts[0] > cnts[1]) { + swap(cnts[0], cnts[1]); + swap(max_cnt[0], max_cnt[1]); + } + + if (!is_balanced(cnts[0], cnts[1])) { + int a = max_cnt[1]; + int b = cnts[1] - max_cnt[1]; + assert(a > 0); + assert(b > 0); + if (a > b) swap(a, b); + assert(is_balanced(a, b)); + } } From 6301d13863c5b52119e8fc0f9bd59eccaf3e4344 Mon Sep 17 00:00:00 2001 From: GitHub Date: Wed, 23 Apr 2025 01:41:30 +0000 Subject: [PATCH 2/7] [auto-verifier] verify commit 50720686e0d2362eac3c146209b47e4f9a5ee349 --- .verify-helper/timestamps.remote.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.verify-helper/timestamps.remote.json b/.verify-helper/timestamps.remote.json index 4f41afdb..186f2271 100644 --- a/.verify-helper/timestamps.remote.json +++ b/.verify-helper/timestamps.remote.json @@ -65,7 +65,7 @@ "tests/library_checker_aizu_tests/graphs/two_edge_components.test.cpp": "2025-02-10 23:30:47 -0700", "tests/library_checker_aizu_tests/handmade_tests/count_paths_forest.test.cpp": "2024-12-15 14:34:10 -0600", "tests/library_checker_aizu_tests/handmade_tests/dsu_size.test.cpp": "2024-12-14 19:50:29 -0600", -"tests/library_checker_aizu_tests/handmade_tests/edge_cd_small_trees.test.cpp": "2024-12-15 17:01:11 -0600", +"tests/library_checker_aizu_tests/handmade_tests/edge_cd_small_trees.test.cpp": "2025-04-22 19:30:56 -0600", "tests/library_checker_aizu_tests/handmade_tests/fib_matrix_expo.test.cpp": "2024-12-14 19:50:29 -0600", "tests/library_checker_aizu_tests/handmade_tests/functional_graph.test.cpp": "2025-02-10 23:30:47 -0700", "tests/library_checker_aizu_tests/handmade_tests/lca_ladder_forest.test.cpp": "2025-02-10 23:30:47 -0700", @@ -124,10 +124,10 @@ "tests/library_checker_aizu_tests/strings/trie.test.cpp": "2024-12-05 10:41:42 -0600", "tests/library_checker_aizu_tests/strings/wildcard_pattern_matching.test.cpp": "2024-12-14 19:50:29 -0600", "tests/library_checker_aizu_tests/trees/count_paths_per_length.test.cpp": "2024-12-15 14:34:10 -0600", -"tests/library_checker_aizu_tests/trees/edge_cd_contour_range_query.test.cpp": "2024-12-15 17:01:11 -0600", -"tests/library_checker_aizu_tests/trees/edge_cd_contour_range_update.test.cpp": "2024-12-15 17:01:11 -0600", -"tests/library_checker_aizu_tests/trees/edge_cd_count_paths_per_length.test.cpp": "2024-12-15 17:01:11 -0600", -"tests/library_checker_aizu_tests/trees/edge_cd_reroot_dp.test.cpp": "2024-12-15 17:01:11 -0600", +"tests/library_checker_aizu_tests/trees/edge_cd_contour_range_query.test.cpp": "2025-04-22 19:30:56 -0600", +"tests/library_checker_aizu_tests/trees/edge_cd_contour_range_update.test.cpp": "2025-04-22 19:30:56 -0600", +"tests/library_checker_aizu_tests/trees/edge_cd_count_paths_per_length.test.cpp": "2025-04-22 19:30:56 -0600", +"tests/library_checker_aizu_tests/trees/edge_cd_reroot_dp.test.cpp": "2025-04-22 19:30:56 -0600", "tests/library_checker_aizu_tests/trees/kth_path_ladder.test.cpp": "2025-02-10 23:30:47 -0700", "tests/library_checker_aizu_tests/trees/kth_path_linear.test.cpp": "2025-02-10 23:30:47 -0700", "tests/library_checker_aizu_tests/trees/kth_path_tree_lift.test.cpp": "2025-02-10 14:50:36 -0700", From 502e4836a561d53b150f1d7284a327be11f5c15d Mon Sep 17 00:00:00 2001 From: Luke Videckis Date: Tue, 22 Apr 2025 20:22:33 -0600 Subject: [PATCH 3/7] updates --- library/trees/edge_cd.hpp | 33 +++++++++---------- .../edge_cd_asserts.hpp | 2 ++ 2 files changed, 17 insertions(+), 18 deletions(-) diff --git a/library/trees/edge_cd.hpp b/library/trees/edge_cd.hpp index eb50f86f..9d68cf30 100644 --- a/library/trees/edge_cd.hpp +++ b/library/trees/edge_cd.hpp @@ -25,37 +25,34 @@ template struct edge_cd { vector adj; F f; - vi sub_sz; - edge_cd(const vector& adj, F f) : adj(adj), f(f), sub_sz(sz(adj)) { - dfs(0, sz(adj)); + vi siz; + edge_cd(const vector& adj, F f) : adj(adj), f(f), siz(sz(adj)) { + dfs(0, sz(adj) - 1); } - int find_cent(int v, int p, int siz) { - sub_sz[v] = 1; + int find_cent(int v, int p, int m) { + siz[v] = 1; for (int u : adj[v]) if (u != p) { - int cent = find_cent(u, v, siz); + int cent = find_cent(u, v, m); if (cent != -1) return cent; - sub_sz[v] += sub_sz[u]; + siz[v] += siz[u]; } if (p == -1) return v; - return 2 * sub_sz[v] >= siz ? sub_sz[p] = siz - sub_sz[v], v : -1; + return 2 * siz[v] > m ? siz[p] = m + 1 - siz[v], v : -1; } - void dfs(int v, int siz) { - if (siz <= 2) return; - v = find_cent(v, -1, siz); + void dfs(int v, int m) { + if (m < 2) return; + v = find_cent(v, -1, m); int sum = 0; auto it = partition(all(adj[v]), [&](int u) { - ll b = sum + sub_sz[u]; - ll a = siz - 1 - b; - bool ret = (b * b <= a * (a + b)); - if (ret) sum += sub_sz[u]; - return ret; + ll x = sum + siz[u]; + return x * x < m * (m - x) ? sum += siz[u], 1 : 0; }); f(adj, v, it - begin(adj[v])); G oth(it, end(adj[v])); adj[v].erase(it, end(adj[v])); - dfs(v, sum + 1); + dfs(v, sum); swap(adj[v], oth); - dfs(v, siz - sum); + dfs(v, m - sum); } }; diff --git a/tests/library_checker_aizu_tests/edge_cd_asserts.hpp b/tests/library_checker_aizu_tests/edge_cd_asserts.hpp index e24c9f7a..00470d0a 100644 --- a/tests/library_checker_aizu_tests/edge_cd_asserts.hpp +++ b/tests/library_checker_aizu_tests/edge_cd_asserts.hpp @@ -42,5 +42,7 @@ void edge_cd_asserts(const vector& adj, int cent, int split) { assert(b > 0); if (a > b) swap(a, b); assert(is_balanced(a, b)); + assert(!is_balanced(a, cnts[0] + b)); + assert(!is_balanced(b, cnts[0] + a)); } } From 0bf23f67f01e61c21f13656e13f858c28efc8cd2 Mon Sep 17 00:00:00 2001 From: Luke Videckis Date: Tue, 22 Apr 2025 20:25:43 -0600 Subject: [PATCH 4/7] Delete library/trees/edge_centroid_decomp_uncommon/README.md --- .../edge_centroid_decomp_uncommon/README.md | 36 ------------------- 1 file changed, 36 deletions(-) delete mode 100644 library/trees/edge_centroid_decomp_uncommon/README.md diff --git a/library/trees/edge_centroid_decomp_uncommon/README.md b/library/trees/edge_centroid_decomp_uncommon/README.md deleted file mode 100644 index 4fe42822..00000000 --- a/library/trees/edge_centroid_decomp_uncommon/README.md +++ /dev/null @@ -1,36 +0,0 @@ -![](edge_cd.png) - -## explanation of the greedy - -think "my edge set", and "the other edge set" - -### the problem - -`3 * (sum + sub_sz[v]) <= 2 * (siz - 1)` is the greedy from https://codeforces.com/blog/entry/104997 but for example once my edge set has more than half the edges (e.g. `2 * sum >= siz - 1`) we potentially can still add to it, making the edge sets even more "unbalanced". - -### the fix - -define balance = `abs(size_of_my_edge_set - size_of_other_edge_set)` - -- before adding `sub_sz[v]`, balance = `abs(sum - (siz - 1 - sum))` -- after adding `sub_sz[v]`, balance = `abs(sum + sub_sz[v] - (siz - 1 - sum - sub_sz[v]))` - -idea: we want to add `v` to my edge set only when that decreases the balance (and my edge set's size stays <= 2/3(siz-1)). - -How to see that `2 * sum + sub_sz[v] < siz - 1` is the same as "adding `sub_sz[v]` to my edge set will decrease the balance"? - -rewrite as `sum + sub_sz[v] < siz - 1 - sum`, now: - -- `sum + sub_sz[v]` = size of my edge set after adding `v` -- `siz - 1 - sum` = size of the other edge set before adding `v` - -so we only add `sub_sz[v]` to my edge set when my edge set afterwards is smaller than the other edge set before. - ---- - -## Will this greedy always give a 1/3-2/3 partition? - -It is clear `3*sum <= 2*(siz-1)` so we just have to show `3*sum >= siz-1` (at the end): - -- if size of my edge set so far `<1/3(siz-1)` then the behavior of this greedy is exactly the same as the one in the blog -- if size of my edge set so far `>=1/3(siz-1)` then we switch the behavior to "only add if the balance decreases" From 818e437764b88a7908af4b711ca77a0adeaefd52 Mon Sep 17 00:00:00 2001 From: Luke Videckis Date: Tue, 22 Apr 2025 20:30:26 -0600 Subject: [PATCH 5/7] format --- library/trees/edge_cd.hpp | 9 ++-- .../edge_cd_asserts.hpp | 10 ++-- .../handmade_tests/functional_graph.test.cpp | 54 ++++++++++--------- .../math/xor_basis.test.cpp | 3 +- 4 files changed, 40 insertions(+), 36 deletions(-) diff --git a/library/trees/edge_cd.hpp b/library/trees/edge_cd.hpp index 9d68cf30..436f6ee5 100644 --- a/library/trees/edge_cd.hpp +++ b/library/trees/edge_cd.hpp @@ -21,12 +21,12 @@ //! handle single-edge-paths separately //! @time O(n logφ n) //! @space O(n) -template -struct edge_cd { +template struct edge_cd { vector adj; F f; vi siz; - edge_cd(const vector& adj, F f) : adj(adj), f(f), siz(sz(adj)) { + edge_cd(const vector& adj, F f): + adj(adj), f(f), siz(sz(adj)) { dfs(0, sz(adj) - 1); } int find_cent(int v, int p, int m) { @@ -38,7 +38,8 @@ struct edge_cd { siz[v] += siz[u]; } if (p == -1) return v; - return 2 * siz[v] > m ? siz[p] = m + 1 - siz[v], v : -1; + return 2 * siz[v] > m ? siz[p] = m + 1 - siz[v], + v : -1; } void dfs(int v, int m) { if (m < 2) return; diff --git a/tests/library_checker_aizu_tests/edge_cd_asserts.hpp b/tests/library_checker_aizu_tests/edge_cd_asserts.hpp index 00470d0a..5fa3fae1 100644 --- a/tests/library_checker_aizu_tests/edge_cd_asserts.hpp +++ b/tests/library_checker_aizu_tests/edge_cd_asserts.hpp @@ -1,5 +1,6 @@ #pragma once -void edge_cd_asserts(const vector& adj, int cent, int split) { +void edge_cd_asserts(const vector& adj, int cent, + int split) { assert(0 < split && split < sz(adj[cent])); auto dfs = [&](auto&& self, int u, int p) -> int { int siz = 1; @@ -15,12 +16,11 @@ void edge_cd_asserts(const vector& adj, int cent, int split) { int sz_subtree = dfs(dfs, adj[cent][i], cent); assert(2 * sz_subtree <= sz_all); cnts[i < split] += sz_subtree; - max_cnt[i < split] = max(max_cnt[i < split], sz_subtree); + max_cnt[i < split] = + max(max_cnt[i < split], sz_subtree); } assert(cnts[0] + cnts[1] + 1 == sz_all); - if (sz_all == 4) return; - // a is the number of edges in the smaller edge set // b is the number of edges in the larger edge set // so we know 1/2 <= b/(a+b) @@ -29,12 +29,10 @@ void edge_cd_asserts(const vector& adj, int cent, int split) { assert(a <= b); return b * b <= a * (a + b); }; - if (cnts[0] > cnts[1]) { swap(cnts[0], cnts[1]); swap(max_cnt[0], max_cnt[1]); } - if (!is_balanced(cnts[0], cnts[1])) { int a = max_cnt[1]; int b = cnts[1] - max_cnt[1]; diff --git a/tests/library_checker_aizu_tests/handmade_tests/functional_graph.test.cpp b/tests/library_checker_aizu_tests/handmade_tests/functional_graph.test.cpp index 4cb44c7c..59ad7319 100644 --- a/tests/library_checker_aizu_tests/handmade_tests/functional_graph.test.cpp +++ b/tests/library_checker_aizu_tests/handmade_tests/functional_graph.test.cpp @@ -1,4 +1,5 @@ -#define PROBLEM "https://onlinejudge.u-aizu.ac.jp/problems/ITP1_1_A" +#define PROBLEM \ + "https://onlinejudge.u-aizu.ac.jp/problems/ITP1_1_A" #include "../template.hpp" #include "../../../library/contest/random.hpp" #include "../../../library/graphs/functional_graph_processor.hpp" @@ -8,7 +9,7 @@ struct functional_graph_processor { init(sz(next)); build(next); } - template + template functional_graph_processor(const Graph_t &g) { init(g.n); build(g); @@ -100,31 +101,30 @@ struct functional_graph_processor { } int n; vector> cycle; - vector cycle_id; // id of the cycle it belongs to, - // -1 if not part of one - vector cycle_pos; // position in its cycle, -1 if - // not part of one - vector cycle_prev; // previous vertex in its cycle, - // -1 if not part of one - vector component_size; // size of its weakly - // connected component - vector root_of; // first reachable node in a cycle - vector depth; // distance to its root - vector> abr; // forest of arborescences of reversed edges not - // on the cycles - vector order; // dfs order of abr - vector pos; // pos in the dfs order - vector end; // [pos[u], end[u]) denotes the subtree - vector size; // size of the subtree in abr + vector cycle_id; // id of the cycle it belongs to, + // -1 if not part of one + vector cycle_pos; // position in its cycle, -1 if + // not part of one + vector cycle_prev; // previous vertex in its cycle, + // -1 if not part of one + vector component_size; // size of its weakly + // connected component + vector root_of; // first reachable node in a cycle + vector depth; // distance to its root + vector> + abr; // forest of arborescences of reversed edges not + // on the cycles + vector order; // dfs order of abr + vector pos; // pos in the dfs order + vector end; // [pos[u], end[u]) denotes the subtree + vector size; // size of the subtree in abr }; - bool equal(const basic_string &a, const vi &b) { if (sz(a) != sz(b)) return 0; for (int i = 0; i < sz(a); i++) if (a[i] != b[i]) return 0; return 1; } - int main() { cin.tie(0)->sync_with_stdio(0); for (int num_tests = 100; num_tests--;) { @@ -135,7 +135,8 @@ int main() { functional_graph_processor fgp(a); assert(cycle == fgp.cycle); for (int i = 0; i < n; i++) { - int root = cycle[t[i].root_of.first][t[i].root_of.second]; + int root = + cycle[t[i].root_of.first][t[i].root_of.second]; assert(root == fgp.root_of[i]); assert(equal(t[i].childs, fgp.abr[i])); assert((root == i) == (fgp.cycle_id[i] != -1)); @@ -143,11 +144,14 @@ int main() { assert(t[i].root_of.first == fgp.cycle_id[i]); assert(t[i].root_of.second == fgp.cycle_pos[i]); int cyc_len = ssize(cycle[t[i].root_of.first]); - assert(cycle[t[i].root_of.first][(t[i].root_of.second + 1) % cyc_len] == - a[i]); + assert( + cycle[t[i].root_of.first] + [(t[i].root_of.second + 1) % cyc_len] == + a[i]); assert(fgp.cycle_prev[i] == - cycle[t[i].root_of.first] - [(t[i].root_of.second - 1 + cyc_len) % cyc_len]); + cycle[t[i].root_of.first] + [(t[i].root_of.second - 1 + cyc_len) % + cyc_len]); } else { assert(fgp.cycle_prev[i] == -1); } diff --git a/tests/library_checker_aizu_tests/math/xor_basis.test.cpp b/tests/library_checker_aizu_tests/math/xor_basis.test.cpp index d44a43f7..d3c4ef70 100644 --- a/tests/library_checker_aizu_tests/math/xor_basis.test.cpp +++ b/tests/library_checker_aizu_tests/math/xor_basis.test.cpp @@ -26,7 +26,8 @@ int main() { int64_t val2 = unordered.shrink(val1); assert(val1 == val2); for (int64_t v : unordered.b) - assert((bit_floor((unsigned long long)v) & val2) == 0); + assert( + (bit_floor((unsigned long long)v) & val2) == 0); bool inserted_unordered = unordered.insert(elem); bool inserted_ordered_ll = ordered_ll.insert(elem); bool inserted_ordered_bitset = From 5e7bd34f36774cd2a6340fa38337db81df6a8360 Mon Sep 17 00:00:00 2001 From: Luke Videckis Date: Tue, 22 Apr 2025 20:30:56 -0600 Subject: [PATCH 6/7] fix --- tests/scripts/ptc.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/scripts/ptc.sh b/tests/scripts/ptc.sh index 43100b42..e1c50304 100755 --- a/tests/scripts/ptc.sh +++ b/tests/scripts/ptc.sh @@ -30,7 +30,6 @@ rm ../library/monotonic_stack/mono_stack_ri.png || exit 1 rm ../library/strings/manacher/longest_palindrome_query.hpp || exit 1 rm ../library/trees/centroid_decomp_uncommon/count_paths_per_length.hpp || exit 1 rm ../library/trees/centroid_decomp_uncommon/count_paths_per_node.hpp || exit 1 -rm ../library/trees/edge_centroid_decomp_uncommon/README.md || exit 1 rm ../library/trees/edge_centroid_decomp_uncommon/contour_range_query.hpp || exit 1 rm ../library/trees/edge_centroid_decomp_uncommon/contour_range_update.hpp || exit 1 rm ../library/trees/edge_centroid_decomp_uncommon/count_paths_per_length.hpp || exit 1 From e591c66658730f6db4e04faa7df88e9929a610c3 Mon Sep 17 00:00:00 2001 From: Luke Videckis Date: Tue, 22 Apr 2025 20:35:58 -0600 Subject: [PATCH 7/7] update complexity --- .../contour_range_query.hpp | 10 +++++----- .../contour_range_update.hpp | 10 +++++----- .../count_paths_per_length.hpp | 2 +- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/library/trees/edge_centroid_decomp_uncommon/contour_range_query.hpp b/library/trees/edge_centroid_decomp_uncommon/contour_range_query.hpp index 34ae003b..4e5d8b80 100644 --- a/library/trees/edge_centroid_decomp_uncommon/contour_range_query.hpp +++ b/library/trees/edge_centroid_decomp_uncommon/contour_range_query.hpp @@ -1,7 +1,7 @@ #pragma once #include "../../data_structures/bit.hpp" -#include "sum_adjacent.hpp" #include "../edge_cd.hpp" +#include "sum_adjacent.hpp" //! https://judge.yosupo.jp/problem/vertex_add_range_contour_sum_on_tree struct contour_range_query { int n; @@ -10,8 +10,8 @@ struct contour_range_query { vector> bits; //! @param adj unrooted, undirected tree //! @param a a[v] = initial number for node v - //! @time O(n log1.5 n) - //! @space O(n log1.5 n) for `info` and `bits` + //! @time O(n logφ n) + //! @space O(n logφ n) for `info` and `bits` contour_range_query(const vector& adj, const vector& a): n(sz(a)), sum_a(adj, a), info(n) { @@ -34,7 +34,7 @@ struct contour_range_query { } //! @param v node //! @param delta number to add to node v's number - //! @time O(log1.5(n) * log2(n)) + //! @time O(logφ(n) * log2(n)) //! @space O(1) void update(int v, ll delta) { sum_a.update(v, delta); @@ -46,7 +46,7 @@ struct contour_range_query { //! @returns sum of node u's number over all u such that //! l //! <= dist_edges(u, v) < r - //! @time O(log1.5(n) * log2(n)) + //! @time O(logφ(n) * log2(n)) //! @space O(1) ll query(int v, int l, int r) { ll sum = 0; diff --git a/library/trees/edge_centroid_decomp_uncommon/contour_range_update.hpp b/library/trees/edge_centroid_decomp_uncommon/contour_range_update.hpp index a8f6257b..c7972172 100644 --- a/library/trees/edge_centroid_decomp_uncommon/contour_range_update.hpp +++ b/library/trees/edge_centroid_decomp_uncommon/contour_range_update.hpp @@ -1,7 +1,7 @@ #pragma once #include "../../data_structures/bit_uncommon/rupq.hpp" -#include "sum_adjacent.hpp" #include "../edge_cd.hpp" +#include "sum_adjacent.hpp" //! https://judge.yosupo.jp/problem/vertex_get_range_contour_add_on_tree struct contour_range_update { int n; @@ -11,8 +11,8 @@ struct contour_range_update { vector> bits; //! @param adj unrooted, undirected tree //! @param a a[v] = initial number for node v - //! @time O(n log1.5 n) - //! @space O(n log1.5 n) for `info` and `bits` + //! @time O(n logφ n) + //! @space O(n logφ n) for `info` and `bits` contour_range_update(const vector& adj, const vector& a): n(sz(a)), a(a), sum_a(adj, vector(n)), info(n) { @@ -34,7 +34,7 @@ struct contour_range_update { } //! @param v,l,r,delta add delta to all nodes u such //! that l <= dist_edges(v, u) < r - //! @time O(log1.5(n) * log2(n)) + //! @time O(logφ(n) * log2(n)) //! @space O(1) void update(int v, int l, int r, ll delta) { if (l <= 0 && 0 < r) a[v] += delta; @@ -48,7 +48,7 @@ struct contour_range_update { } //! @param v node //! @returns number of node v - //! @time O(log1.5(n) * log2(n)) + //! @time O(logφ(n) * log2(n)) //! @space O(1) ll query(int v) { ll sum = a[v] + sum_a.query(v); diff --git a/library/trees/edge_centroid_decomp_uncommon/count_paths_per_length.hpp b/library/trees/edge_centroid_decomp_uncommon/count_paths_per_length.hpp index cc4adb40..5cff30fa 100644 --- a/library/trees/edge_centroid_decomp_uncommon/count_paths_per_length.hpp +++ b/library/trees/edge_centroid_decomp_uncommon/count_paths_per_length.hpp @@ -4,7 +4,7 @@ //! @param adj unrooted, connected tree //! @returns array `num_paths` where `num_paths[i]` = # of //! paths in tree with `i` edges. `num_paths[1]` = # edges -//! @time O(n * log1.5(n) * log2(n)) +//! @time O(n * logφ(n) * log2(n)) //! @space this function allocates/returns various vectors //! which are each O(n) vector count_paths_per_length(const vector& adj) {