Skip to content

Commit 92d9997

Browse files
Add find_last_left method for typical_segment_tree
1 parent 16b2186 commit 92d9997

File tree

3 files changed

+48
-3
lines changed

3 files changed

+48
-3
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,4 @@ library/test.exe
77
library/test.d
88
.yarn/
99
*.gch
10+
tmp/

library/mrpython/typical_segment_tree.hpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ template <typename T, typename MergeFunction> class typical_segment_tree {
101101
T getd(size_t l, size_t r, T const& e = {}) { return l == r ? e : get(l, r); }
102102
template <typename Check>
103103
size_t find_first_right(size_t l, Check const& check) {
104+
if (l >= n) return l;
104105
l = data_id_to_node_id(l);
105106
while (l % 2 == 1) l /= 2;
106107
while (l < 2 * n - 1 && check(data[l])) l = l * 2 + 1;
@@ -120,6 +121,28 @@ template <typename T, typename MergeFunction> class typical_segment_tree {
120121
}
121122
return node_id_to_data_id(l);
122123
}
124+
template <typename Check>
125+
size_t find_last_left(size_t r, Check const& check) {
126+
if (r >= n) return r;
127+
r = data_id_to_node_id(r);
128+
while (r && r % 2 == 0) r = (r - 1) / 2;
129+
while (r < 2 * n - 1 && check(data[r])) r = r * 2 + 2;
130+
if (r >= 2 * n - 1) return node_id_to_data_id((r - 1) / 2);
131+
T v = data[r];
132+
do {
133+
if (!(r & (r + 1))) return -1;
134+
--r;
135+
while (r % 2 == 0) r = (r - 1) / 2;
136+
} while (!check(data[r]));
137+
while (r < n - 1) {
138+
T vr = merge(v, data[r * 2 + 2]);
139+
if (!check(vr))
140+
r = r * 2 + 1, v = vr;
141+
else
142+
r = r * 2 + 2;
143+
}
144+
return node_id_to_data_id(r);
145+
}
123146
};
124147
template <typename T>
125148
using typical_segment_tree_add = typical_segment_tree<T, std::plus<T>>;

library/test/typical_segment_tree/typical_segment_tree_min.cpp

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#include <gtest/gtest.h>
22

3+
#include <cstddef>
34
#include <mrpython/typical_segment_tree.hpp>
4-
#include <numeric>
55
#include <random>
66

77
TEST(typical_segment_tree, min) {
@@ -30,14 +30,14 @@ TEST(typical_segment_tree, min) {
3030
}
3131
}
3232

33-
TEST(typicaL_segment_tree, fist_first_right) {
33+
TEST(typicaL_segment_tree, find_first_right) {
3434
std::mt19937_64 gen(std::random_device{}());
3535
std::size_t n = std::uniform_int_distribution<std::size_t>{1, 5000}(gen),
3636
q = std::uniform_int_distribution<std::size_t>{1, 5000}(gen);
3737
std::vector<int> a(n);
3838
std::uniform_int_distribution<int> val_dist(std::numeric_limits<int>::min(),
3939
std::numeric_limits<int>::max());
40-
std::uniform_int_distribution<std::size_t> size_dist(0, n - 1),
40+
std::uniform_int_distribution<std::size_t> size_dist(0, n),
4141
operator_dist(0, 1);
4242
std::generate(a.begin(), a.end(), [&] { return val_dist(gen); });
4343
mrpython::typical_segment_tree_min<int> tree(a.begin(), a.end());
@@ -49,3 +49,24 @@ TEST(typicaL_segment_tree, fist_first_right) {
4949
EXPECT_EQ(tree.find_first_right(l, check), ans);
5050
}
5151
}
52+
53+
TEST(typicaL_segment_tree, find_last_left) {
54+
std::mt19937_64 gen(std::random_device{}());
55+
std::size_t n = std::uniform_int_distribution<std::size_t>{1, 5000}(gen),
56+
q = std::uniform_int_distribution<std::size_t>{1, 5000}(gen);
57+
std::vector<int> a(n);
58+
std::uniform_int_distribution<int> val_dist(std::numeric_limits<int>::min(),
59+
std::numeric_limits<int>::max());
60+
std::uniform_int_distribution<std::size_t> size_dist(0, n),
61+
operator_dist(0, 1);
62+
std::generate(a.begin(), a.end(), [&] { return val_dist(gen); });
63+
mrpython::typical_segment_tree_min<int> tree(a.begin(), a.end());
64+
while (q--) {
65+
std::size_t l = size_dist(gen) - 1;
66+
int tv = val_dist(gen);
67+
auto check = [tv](int x) { return x <= tv; };
68+
size_t ans = a.rend() - std::find_if(a.rend() - l - 1, a.rend(), check) - 1;
69+
size_t out = tree.find_last_left(l, check);
70+
EXPECT_EQ(out, ans);
71+
}
72+
}

0 commit comments

Comments
 (0)