Skip to content

Commit b579b48

Browse files
lrvideckisweb-flow
andauthored
refactor (#189)
* refactor * fix * [auto-verifier] verify commit 3781dff * add min left now * rename * [auto-verifier] verify commit 30158ac * update * fix test * update test * finally debugged it * [auto-verifier] verify commit 8102111 * update docs * fix * update * fix * fix docs * [auto-verifier] verify commit a2a9464 --------- Co-authored-by: GitHub <noreply@github.com>
1 parent d25d6e5 commit b579b48

File tree

12 files changed

+166
-59
lines changed

12 files changed

+166
-59
lines changed

.verify-helper/timestamps.remote.json

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,12 @@
3535
"tests/library_checker_aizu_tests/data_structures/rmq_linear.test.cpp": "2026-01-18 11:15:41 +0000",
3636
"tests/library_checker_aizu_tests/data_structures/rmq_sparse_table.test.cpp": "2026-01-18 11:15:41 +0000",
3737
"tests/library_checker_aizu_tests/data_structures/rmq_sparse_table_inc.test.cpp": "2026-01-18 11:15:41 +0000",
38-
"tests/library_checker_aizu_tests/data_structures/simple_tree.test.cpp": "2026-02-14 20:58:21 +0000",
39-
"tests/library_checker_aizu_tests/data_structures/simple_tree_inc.test.cpp": "2026-02-16 16:56:58 -0700",
40-
"tests/library_checker_aizu_tests/data_structures/simple_tree_inc_line.test.cpp": "2026-02-16 16:56:58 -0700",
41-
"tests/library_checker_aizu_tests/data_structures/simple_tree_inc_walk.test.cpp": "2026-02-16 16:56:58 -0700",
42-
"tests/library_checker_aizu_tests/data_structures/simple_tree_line.test.cpp": "2026-02-14 20:58:21 +0000",
43-
"tests/library_checker_aizu_tests/data_structures/simple_tree_walk.test.cpp": "2026-02-14 20:58:21 +0000",
38+
"tests/library_checker_aizu_tests/data_structures/simple_tree.test.cpp": "2026-03-01 19:25:42 -0700",
39+
"tests/library_checker_aizu_tests/data_structures/simple_tree_inc.test.cpp": "2026-03-01 19:20:06 -0700",
40+
"tests/library_checker_aizu_tests/data_structures/simple_tree_inc_line.test.cpp": "2026-03-01 19:20:06 -0700",
41+
"tests/library_checker_aizu_tests/data_structures/simple_tree_inc_walk.test.cpp": "2026-03-01 19:20:06 -0700",
42+
"tests/library_checker_aizu_tests/data_structures/simple_tree_line.test.cpp": "2026-03-01 19:25:42 -0700",
43+
"tests/library_checker_aizu_tests/data_structures/simple_tree_walk.test.cpp": "2026-03-01 19:25:42 -0700",
4444
"tests/library_checker_aizu_tests/dsu/dsu.test.cpp": "2026-02-27 15:26:53 -0700",
4545
"tests/library_checker_aizu_tests/dsu/dsu_bipartite.test.cpp": "2026-02-27 15:26:53 -0700",
4646
"tests/library_checker_aizu_tests/dsu/kruskal_tree_aizu.test.cpp": "2026-02-27 15:26:53 -0700",

library/data_structures_[l,r)/seg_tree.hpp

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,22 @@
22
//! https://github.com/kth-competitive-programming/kactl/blob/main/content/data-structures/SegmentTree.h
33
//! https://codeforces.com/blog/entry/118682
44
//! @code
5-
//! tree st1(n, INT_MAX, ranges::min);
6-
//! tree st2(n, INT_MAX, [&](int x, int y) -> int {
7-
//! return min(x, y);
5+
//! tree st1(n, 0, [&](int vl, int vr) {
6+
//! return vl + vr;
87
//! });
9-
//! int idx = st2.walk(l, r, [&](int value) {
10-
//! return value > x;
11-
//! }); // min idx in [l, r) such that f is false
8+
//! tree st(n, INT_MAX, ranges::min);
9+
//! int idx = st.max_right(l, r, [&](int value) {
10+
//! return value <= x;
11+
//! });
12+
//! // idx in [l, r]
13+
//! // f(op(a[l], a[l+1], ..., a[idx-1])) is true
14+
//! // f(op(a[l], a[l+1], ..., a[idx])) is false
15+
//! idx = st.min_left(l, r, [&](int value) {
16+
//! return value <= x;
17+
//! });
18+
//! // idx in [l, r]
19+
//! // f(op(a[idx], ..., a[r-2], a[r-1])) is true
20+
//! // f(op(a[idx-1], ..., a[r-2], a[r-1])) is false
1221
//! @endcode
1322
//! @time O(n + q log n)
1423
//! @space O(n)
@@ -31,5 +40,6 @@ template<class T, class F> struct tree {
3140
}
3241
return op(x, y);
3342
}
34-
#include "seg_tree_uncommon/walk.hpp"
43+
#include "seg_tree_uncommon/max_right.hpp"
44+
#include "seg_tree_uncommon/min_left.hpp"
3545
};

library/data_structures_[l,r)/seg_tree_uncommon/walk.hpp renamed to library/data_structures_[l,r)/seg_tree_uncommon/max_right.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
int walk(int l, int r, const auto& f) {
1+
int max_right(int l, int r, const auto& f) {
22
for (T x = unit; l < r;) {
33
int u = l + n, v = __lg(min(u & -u, r - l));
44
if (T y = op(x, s[u >> v]); f(y)) l += 1 << v, x = y;
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
int min_left(int l, int r, const auto& f) {
2+
for (T x = unit; l < r;) {
3+
int u = r + n, v = __lg(min(u & -u, r - l));
4+
if (T y = op(s[(u - 1) >> v], x); f(y))
5+
r -= 1 << v, x = y;
6+
else l = r - (1 << v) + 1;
7+
}
8+
return r;
9+
}

library/data_structures_[l,r]/seg_tree.hpp

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,22 @@
11
#pragma once
22
//! https://codeforces.com/blog/entry/118682
33
//! @code
4-
//! {
5-
//! tree st(a, [&](int vl, int vr) {
6-
//! return vl & vr;
7-
//! });
8-
//! }
9-
//! {
10-
//! tree st(n, 0LL, plus<ll>{});
11-
//! }
12-
//! {
13-
//! tree st(n, INT_MAX, ranges::min);
14-
//! int idx = st.walk(l, r, [&](int value) {
15-
//! return value <= x;
16-
//! }); // smallest index in [l, r] s.t. f is false
17-
//! }
4+
//! tree st1(n, 0, [&](int vl, int vr) {
5+
//! return vl + vr;
6+
//! });
7+
//! tree st(a, ranges::min);
8+
//! int idx = st.max_right(l, r, [&](int value) {
9+
//! return value <= x;
10+
//! });
11+
//! // idx in [l, r+1]
12+
//! // f(op(a[l], a[l+1], ..., a[idx-1])) is true
13+
//! // f(op(a[l], a[l+1], ..., a[idx])) is false
14+
//! idx = st.min_left(l, r, [&](int value) {
15+
//! return value <= x;
16+
//! });
17+
//! // idx in [l-1, r]
18+
//! // f(op(a[idx+1], ..., a[r-1], a[r])) is true
19+
//! // f(op(a[idx], ..., a[r-1], a[r])) is false
1820
//! @endcode
1921
//! @time O(n + q log n)
2022
//! @space O(n)
@@ -38,5 +40,6 @@ template<class T, class F> struct tree {
3840
while (l <= r) x = op(x, s[nxt(l, r)]);
3941
return x;
4042
}
41-
#include "seg_tree_uncommon/walk.hpp"
43+
#include "seg_tree_uncommon/max_right.hpp"
44+
#include "seg_tree_uncommon/min_left.hpp"
4245
};

library/data_structures_[l,r]/seg_tree_uncommon/walk.hpp renamed to library/data_structures_[l,r]/seg_tree_uncommon/max_right.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
int walk(int l, int r, const auto& f) {
1+
int max_right(int l, int r, const auto& f) {
22
if (T x = s[l + n]; f(x))
33
for (l++; l <= r;) {
44
int u = l + n, v = __lg(min(u & -u, r - l + 1));
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
int min_left(int l, int r, const auto& f) {
2+
if (T x = s[r + n]; f(x))
3+
for (r--; l <= r;) {
4+
int u = r + 1 + n, v = __lg(min(u & -u, r - l + 1));
5+
if (T y = op(s[(u - 1) >> v], x); f(y))
6+
r -= 1 << v, x = y;
7+
else l = r - (1 << v) + 2;
8+
}
9+
return r;
10+
}

tests/.config/.code_snippet_excluded_file_list

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,5 @@ prev.hpp
2222
next.hpp
2323
wavelet_count_less.hpp
2424
dynamic_bitset.hpp
25+
max_right.hpp
26+
min_left.hpp

tests/library_checker_aizu_tests/data_structures/simple_tree_inc_line.test.cpp

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ int main() {
1515
return {int(1LL * l[0] * r[0] % mod),
1616
int((1LL * r[0] * l[1] + r[1]) % mod)};
1717
});
18+
const array<int, 2> unit = {1, 0};
1819
while (q--) {
1920
int type;
2021
cin >> type;
@@ -25,8 +26,49 @@ int main() {
2526
} else {
2627
int l, r, x;
2728
cin >> l >> r >> x;
28-
auto [slope, y_int] = st.query(l, r - 1);
29-
cout << (1LL * slope * x + y_int) % mod << '\n';
29+
r--;
30+
array<int, 2> res = st.query(l, r);
31+
{
32+
array<int, 2> walk_res = {1, 0};
33+
int idx = st.max_right(l, r,
34+
[&](const array<int, 2>& curr_line) -> bool {
35+
walk_res = curr_line;
36+
return 1;
37+
});
38+
assert(res == walk_res);
39+
assert(idx == r + 1);
40+
}
41+
{
42+
array<int, 2> walk_res = unit;
43+
int idx = st.max_right(l, r,
44+
[&](const array<int, 2>& curr_line) -> bool {
45+
walk_res = curr_line;
46+
return 0;
47+
});
48+
assert(walk_res == st.query(l, l));
49+
assert(idx == l);
50+
}
51+
{
52+
array<int, 2> walk_res = unit;
53+
int idx = st.min_left(l, r,
54+
[&](const array<int, 2>& curr_line) -> bool {
55+
walk_res = curr_line;
56+
return 1;
57+
});
58+
assert(walk_res == res);
59+
assert(idx == l - 1);
60+
}
61+
{
62+
array<int, 2> walk_res = unit;
63+
int idx = st.min_left(l, r,
64+
[&](const array<int, 2>& curr_line) -> bool {
65+
walk_res = curr_line;
66+
return 0;
67+
});
68+
assert(walk_res == st.query(r, r));
69+
assert(idx == r);
70+
}
71+
cout << (1LL * res[0] * x + res[1]) % mod << '\n';
3072
}
3173
}
3274
return 0;

tests/library_checker_aizu_tests/data_structures/simple_tree_inc_walk.test.cpp

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ int main() {
1010
cin >> s;
1111
vector<int> init(n);
1212
for (int i = 0; i < n; i++) init[i] = s[i] - '0';
13-
tree st(init, plus<int>{});
13+
tree st(init, ranges::max);
1414
while (q--) {
1515
int type, k;
1616
cin >> type >> k;
@@ -21,21 +21,16 @@ int main() {
2121
} else if (type == 2) {
2222
cout << st.query(k, k) << '\n';
2323
} else if (type == 3) {
24-
// returns first element in [k,n-1] such that sum > 0
25-
int idx = st.walk(k, n - 1,
26-
[&](int sum) { return sum == 0; });
24+
// returns first element in [k,n-1] such that mx > 0
25+
int idx = st.max_right(k, n - 1,
26+
[&](int mx) { return mx == 0; });
2727
if (idx == n) idx = -1;
2828
cout << idx << '\n';
2929
} else {
3030
assert(type == 4);
31-
int total = st.query(0, k);
32-
if (total == 0) {
33-
cout << -1 << '\n';
34-
} else {
35-
cout << st.walk(0, k, [&](int sum) {
36-
return sum < total;
37-
}) << '\n';
38-
}
31+
cout << st.min_left(0, k, [&](int mx) {
32+
return mx == 0;
33+
}) << '\n';
3934
}
4035
}
4136
return 0;

0 commit comments

Comments
 (0)