Skip to content

Commit c338f94

Browse files
author
Cameron Custer
committed
seg_tree: max_right/min_left return the boundary index
1 parent 03e2eec commit c338f94

7 files changed

Lines changed: 41 additions & 47 deletions

File tree

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

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,16 @@
66
//! return vl + vr;
77
//! });
88
//! tree st(n, LLONG_MAX, ranges::min);
9-
//! st.max_right(l, r, [&](int m, ll value) -> bool {
10-
//! // l < m <= r
11-
//! // value = op(a[l], a[l+1], ..., a[m-1])
12-
//! });
13-
//! st.min_left(l, r, [&](int m, ll value) -> bool {
14-
//! // l <= m < r
15-
//! // value = op(a[m], ..., a[r-2], a[r-1])
16-
//! });
9+
//! int m1 = st.max_right(l, r,
10+
//! [&](int m, ll value) -> bool {
11+
//! // l < m <= r
12+
//! // value = op(a[l], a[l+1], ..., a[m-1])
13+
//! }); // max m such that f holds; l if none
14+
//! int m2 = st.min_left(l, r,
15+
//! [&](int m, ll value) -> bool {
16+
//! // l <= m < r
17+
//! // value = op(a[m], ..., a[r-2], a[r-1])
18+
//! }); // min m such that f holds; r if none
1719
//! @endcode
1820
//! @time O(n + q log n)
1921
//! @space O(n)
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1-
void max_right(int l, int r, auto f) {
1+
int max_right(int l, int r, auto f) {
22
for (T x = unit; l < r;) {
33
int u = l + n,
44
v = bit_width(min(u & -u, r - l) + 0u) - 1,
55
m = l + (1 << v);
66
if (T y = op(x, s[u >> v]); f(m, y)) l = m, x = y;
77
else r = m - 1;
88
}
9+
return l;
910
}
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
void min_left(int l, int r, auto f) {
1+
int min_left(int l, int r, auto f) {
22
for (T x = unit; l < r;) {
33
int u = r + n,
44
v = bit_width(min(u & -u, r - l) + 0u) - 1,
@@ -7,4 +7,5 @@ void min_left(int l, int r, auto f) {
77
r = m, x = y;
88
else l = m + 1;
99
}
10+
return r;
1011
}

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

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,16 @@
55
//! return vl + vr;
66
//! });
77
//! tree st(n, LLONG_MAX, ranges::min);
8-
//! st.max_right(l, r, [&](int m, ll value) -> bool {
9-
//! // l <= m <= r
10-
//! // value = op(a[l], a[l+1], ..., a[m])
11-
//! });
12-
//! st.min_left(l, r, [&](int m, ll value) -> bool {
13-
//! // l <= m <= r
14-
//! // value = op(a[m], ..., a[r-1], a[r])
15-
//! });
8+
//! int m1 = st.max_right(l, r,
9+
//! [&](int m, ll value) -> bool {
10+
//! // l <= m <= r
11+
//! // value = op(a[l], a[l+1], ..., a[m])
12+
//! }); // min m such that f fails; r+1 if none
13+
//! int m2 = st.min_left(l, r,
14+
//! [&](int m, ll value) -> bool {
15+
//! // l <= m <= r
16+
//! // value = op(a[m], ..., a[r-1], a[r])
17+
//! }); // max m such that f fails; l-1 if none
1618
//! @endcode
1719
//! @time O(n + q log n)
1820
//! @space O(n)

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
void max_right(int l, int r, auto f) {
1+
int max_right(int l, int r, auto f) {
22
if (T x = s[l + n]; f(l, x))
33
for (l++; l <= r;) {
44
int u = l + n,
@@ -8,4 +8,5 @@ void max_right(int l, int r, auto f) {
88
l = m + 1, x = y;
99
else r = m - 1;
1010
}
11+
return l;
1112
}

tests/library_checker_aizu_tests/data_structures/simple_tree_inc_walk.test.cpp

Lines changed: 7 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -21,21 +21,15 @@ 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 mx > 0
25-
int idx = -1;
26-
st.max_right(k, n - 1, [&](int m, int mx) {
27-
if (mx == 0) return 1;
28-
idx = m;
29-
return 0;
30-
});
31-
cout << idx << '\n';
24+
// index of first element in [k,n-1] such that mx > 0
25+
int idx = st.max_right(k, n - 1,
26+
[&](int, int mx) { return mx == 0; });
27+
cout << (idx == n ? -1 : idx) << '\n';
3228
} else {
3329
assert(type == 4);
34-
int idx = -1;
35-
cout << st.min_left(0, k, [&](int m, int mx) {
36-
if (mx == 0) return 1;
37-
idx = m;
38-
return 0;
30+
// index of last element in [0,k] such that mx > 0
31+
cout << st.min_left(0, k, [&](int, int mx) {
32+
return mx == 0;
3933
}) << '\n';
4034
}
4135
}

tests/library_checker_aizu_tests/data_structures/simple_tree_walk.test.cpp

Lines changed: 8 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -20,23 +20,16 @@ int main() {
2020
} else if (type == 2) {
2121
cout << st.query(k, k + 1) << '\n';
2222
} else if (type == 3) {
23-
// returns first element in [k,n) such that mx > 0
24-
int idx = -1;
25-
st.max_right(k, n, [&](int m, int mx) {
26-
if (mx == 0) return 1;
27-
idx = m - 1;
28-
return 0;
29-
});
30-
cout << idx << '\n';
23+
// index of first element in [k,n) such that mx > 0
24+
int idx = st.max_right(k, n,
25+
[&](int, int mx) { return mx == 0; });
26+
cout << (idx == n ? -1 : idx) << '\n';
3127
} else {
3228
assert(type == 4);
33-
int idx = -1;
34-
st.min_left(0, k + 1, [&](int m, int mx) {
35-
if (mx == 0) return 1;
36-
idx = m;
37-
return 0;
38-
});
39-
cout << idx << '\n';
29+
// index of last element in [0,k] such that mx > 0
30+
int idx = st.min_left(0, k + 1,
31+
[&](int, int mx) { return mx == 0; });
32+
cout << idx - 1 << '\n';
4033
}
4134
}
4235
return 0;

0 commit comments

Comments
 (0)