Skip to content

Commit b35ec8b

Browse files
lrvideckisweb-flow
andauthored
Linear rmq nits and golf (#147)
* different style + nits * [auto-verifier] verify commit 1f5281b * fixes * [auto-verifier] verify commit 278d085 * format * [auto-verifier] verify commit 03e2059 * suppress * another golf * [auto-verifier] verify commit 60546c3 * another style nit * another golf * another golf * [auto-verifier] verify commit c7f4999 * will hopefully fix the warning * revert to fix warning * [auto-verifier] verify commit 822e46a * nit * [auto-verifier] verify commit 4d6a02b * I like this way * more golf * more golf --------- Co-authored-by: GitHub <noreply@github.com>
1 parent 706fadf commit b35ec8b

File tree

6 files changed

+43
-45
lines changed

6 files changed

+43
-45
lines changed

.verify-helper/timestamps.remote.json

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -33,15 +33,15 @@
3333
"tests/library_checker_aizu_tests/data_structures/line_tree_lib_checker.test.cpp": "2025-02-10 23:30:47 -0700",
3434
"tests/library_checker_aizu_tests/data_structures/merge_sort_tree.test.cpp": "2025-02-11 13:53:30 -0700",
3535
"tests/library_checker_aizu_tests/data_structures/mode_query.test.cpp": "2025-02-10 23:30:47 -0700",
36-
"tests/library_checker_aizu_tests/data_structures/permutation_tree.test.cpp": "2025-06-03 13:37:20 -0600",
36+
"tests/library_checker_aizu_tests/data_structures/permutation_tree.test.cpp": "2025-08-03 18:39:58 -0600",
3737
"tests/library_checker_aizu_tests/data_structures/persistent_queue_tree.test.cpp": "2025-02-10 14:50:36 -0700",
3838
"tests/library_checker_aizu_tests/data_structures/persistent_seg_tree.test.cpp": "2024-12-05 10:41:42 -0600",
3939
"tests/library_checker_aizu_tests/data_structures/pq_ds_undo_sliding_window.test.cpp": "2025-02-10 14:50:36 -0700",
4040
"tests/library_checker_aizu_tests/data_structures/pq_ds_undo_with_dsu.test.cpp": "2025-02-10 14:50:36 -0700",
4141
"tests/library_checker_aizu_tests/data_structures/range_parallel_dsu.test.cpp": "2025-02-10 23:30:47 -0700",
4242
"tests/library_checker_aizu_tests/data_structures/rmq_disjoint_sparse_table.test.cpp": "2024-12-15 14:34:10 -0600",
43-
"tests/library_checker_aizu_tests/data_structures/rmq_linear.test.cpp": "2025-06-03 13:37:20 -0600",
44-
"tests/library_checker_aizu_tests/data_structures/rmq_sparse_table.test.cpp": "2025-06-03 13:37:20 -0600",
43+
"tests/library_checker_aizu_tests/data_structures/rmq_linear.test.cpp": "2025-08-03 18:39:58 -0600",
44+
"tests/library_checker_aizu_tests/data_structures/rmq_sparse_table.test.cpp": "2025-08-03 18:39:58 -0600",
4545
"tests/library_checker_aizu_tests/data_structures/rmq_sparse_table_inc.test.cpp": "2024-12-15 14:34:10 -0600",
4646
"tests/library_checker_aizu_tests/data_structures/simple_tree.test.cpp": "2024-12-14 15:47:13 -0600",
4747
"tests/library_checker_aizu_tests/data_structures/simple_tree_inc.test.cpp": "2024-12-21 00:23:10 -0500",
@@ -78,8 +78,8 @@
7878
"tests/library_checker_aizu_tests/handmade_tests/mobius.test.cpp": "2025-02-10 14:50:36 -0700",
7979
"tests/library_checker_aizu_tests/handmade_tests/mod_int.test.cpp": "2024-12-14 19:50:29 -0600",
8080
"tests/library_checker_aizu_tests/handmade_tests/n_choose_k.test.cpp": "2025-01-15 00:22:31 -0700",
81-
"tests/library_checker_aizu_tests/handmade_tests/permutation_tree_small.test.cpp": "2025-06-03 13:37:20 -0600",
82-
"tests/library_checker_aizu_tests/handmade_tests/rmq_small_n.test.cpp": "2025-06-03 13:37:20 -0600",
81+
"tests/library_checker_aizu_tests/handmade_tests/permutation_tree_small.test.cpp": "2025-08-03 18:39:58 -0600",
82+
"tests/library_checker_aizu_tests/handmade_tests/rmq_small_n.test.cpp": "2025-08-03 18:39:58 -0600",
8383
"tests/library_checker_aizu_tests/handmade_tests/sa_find_subarray.test.cpp": "2025-02-10 14:50:36 -0700",
8484
"tests/library_checker_aizu_tests/handmade_tests/seg_tree_find.test.cpp": "2024-12-14 19:50:29 -0600",
8585
"tests/library_checker_aizu_tests/handmade_tests/seg_tree_find_small.test.cpp": "2024-12-14 19:50:29 -0600",
@@ -107,9 +107,9 @@
107107
"tests/library_checker_aizu_tests/math/xor_basis.test.cpp": "2025-04-22 21:37:22 -0500",
108108
"tests/library_checker_aizu_tests/math/xor_basis_intersection.test.cpp": "2025-02-10 23:30:47 -0700",
109109
"tests/library_checker_aizu_tests/monotonic_stack_related/cartesian_binary_tree.test.cpp": "2025-02-10 14:50:36 -0700",
110-
"tests/library_checker_aizu_tests/monotonic_stack_related/cartesian_k_ary_tree.test.cpp": "2025-06-03 13:37:20 -0600",
111-
"tests/library_checker_aizu_tests/monotonic_stack_related/count_rectangles.test.cpp": "2025-06-03 13:37:20 -0600",
112-
"tests/library_checker_aizu_tests/monotonic_stack_related/max_rect_histogram.test.cpp": "2025-06-03 13:37:20 -0600",
110+
"tests/library_checker_aizu_tests/monotonic_stack_related/cartesian_k_ary_tree.test.cpp": "2025-08-03 18:39:58 -0600",
111+
"tests/library_checker_aizu_tests/monotonic_stack_related/count_rectangles.test.cpp": "2025-08-03 18:39:58 -0600",
112+
"tests/library_checker_aizu_tests/monotonic_stack_related/max_rect_histogram.test.cpp": "2025-08-03 18:39:58 -0600",
113113
"tests/library_checker_aizu_tests/strings/kmp.test.cpp": "2024-12-14 19:50:29 -0600",
114114
"tests/library_checker_aizu_tests/strings/lcp_array.test.cpp": "2025-02-10 14:50:36 -0700",
115115
"tests/library_checker_aizu_tests/strings/lcp_query_palindrome.test.cpp": "2025-02-10 14:50:36 -0700",
@@ -123,7 +123,7 @@
123123
"tests/library_checker_aizu_tests/strings/sa_cmp.test.cpp": "2025-02-10 14:50:36 -0700",
124124
"tests/library_checker_aizu_tests/strings/sa_sort_pairs.test.cpp": "2025-02-10 14:50:36 -0700",
125125
"tests/library_checker_aizu_tests/strings/single_matching_bs.test.cpp": "2025-02-10 14:50:36 -0700",
126-
"tests/library_checker_aizu_tests/strings/suffix_array.test.cpp": "2025-06-03 13:37:20 -0600",
126+
"tests/library_checker_aizu_tests/strings/suffix_array.test.cpp": "2025-08-03 18:39:58 -0600",
127127
"tests/library_checker_aizu_tests/strings/suffix_array_short.test.cpp": "2025-02-10 14:50:36 -0700",
128128
"tests/library_checker_aizu_tests/strings/trie.test.cpp": "2024-12-05 10:41:42 -0600",
129129
"tests/library_checker_aizu_tests/strings/wildcard_pattern_matching.test.cpp": "2024-12-14 19:50:29 -0600",
Lines changed: 25 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,47 @@
11
#pragma once
22
//! https://codeforces.com/blog/entry/125371?#comment-1173604
33
//! @code
4-
//! linear_rmq rmq1(a, less());//right-most min
5-
//! linear_rmq rmq2(a, less_equal());//left-most min
6-
//! linear_rmq rmq3(a, greater());//right-most max
7-
//! linear_rmq rmq4(a, greater_equal());//left-most max
4+
//! linear_rmq rmq1(a, less()); //right-most min
5+
//! linear_rmq rmq2(a, less_equal()); //left-most min
6+
//! linear_rmq rmq3(a, greater()); //right-most max
7+
//! linear_rmq rmq4(a, greater_equal()); //left-most max
88
//! linear_rmq rmq5(a, [&](auto& x, auto& y) {
99
//! return x < y;
1010
//! });
1111
//! @endcode
1212
//! @time O(n + q)
1313
//! @space O(n)
1414
template<class T, class F> struct linear_rmq {
15+
int n;
1516
vector<T> a;
1617
F cmp;
17-
vi head;
18-
vector<array<int, 2>> t;
18+
vi in, asc, head;
1919
linear_rmq(const vector<T>& a, F cmp):
20-
a(a), cmp(cmp), head(sz(a) + 1), t(sz(a)) {
20+
n(sz(a)), a(a), cmp(cmp), in(n), asc(n), head(n + 1) {
2121
vi st{-1};
22-
for (int i = 0; i <= sz(a); i++) {
23-
int prev = -1;
24-
while (st.back() != -1 &&
25-
(i == sz(a) || !cmp(a[st.back()], a[i]))) {
26-
if (prev != -1) head[prev] = st.back();
27-
int pw2 = 1 << __lg((end(st)[-2] + 1) ^ i);
28-
t[st.back()][0] = prev = i & -pw2;
22+
rep(i, 0, n + 1) {
23+
int prev = 0;
24+
while (sz(st) > 1 &&
25+
(i == n || !cmp(a[st.back()], a[i]))) {
26+
head[prev] = st.back();
27+
auto k = end(st)[-2] + 1u, b = bit_floor(k ^ i);
28+
in[st.back()] = prev = i & -b, asc[k] |= b;
2929
st.pop_back();
30-
t[st.back() + 1][1] |= pw2;
3130
}
32-
if (prev != -1) head[prev] = i;
33-
st.push_back(i);
31+
st.push_back(head[prev] = i);
3432
}
35-
rep(i, 1, sz(a)) t[i][1] =
36-
(t[i][1] | t[i - 1][1]) & -(t[i][0] & -t[i][0]);
33+
rep(i, 1, n) asc[i] =
34+
(asc[i] | asc[i - 1]) & -(in[i] & -in[i]);
3735
}
38-
int query_idx(int l, int r) { // [l, r]
39-
if (unsigned j = t[l][0] ^ t[r][0]; j) {
40-
j = t[l][1] & t[r][1] & -bit_floor(j);
41-
if (unsigned k = t[l][1] ^ j; k)
42-
k = bit_floor(k), l = head[(t[l][0] & -k) | k];
43-
if (unsigned k = t[r][1] ^ j; k)
44-
k = bit_floor(k), r = head[(t[r][0] & -k) | k];
36+
int idx(int l, int r) { // [l, r]
37+
if (unsigned j = in[l] ^ in[r]; j) {
38+
j = asc[l] & asc[r] & -bit_floor(j);
39+
if (unsigned k = asc[l] ^ j; k)
40+
k = bit_floor(k), l = head[(in[l] & -k) | k];
41+
if (unsigned k = asc[r] ^ j; k)
42+
k = bit_floor(k), r = head[(in[r] & -k) | k];
4543
}
4644
return cmp(a[l], a[r]) ? l : r;
4745
}
48-
T query(int l, int r) { return a[query_idx(l, r)]; }
46+
T query(int l, int r) { return a[idx(l, r)]; }
4947
};

library/data_structures/uncommon/permutation_tree.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,8 @@ struct perm_tree {
3737
linear_rmq rmq_min(a_inv, less());
3838
linear_rmq rmq_max(a_inv, greater());
3939
rep(i, 1, n) {
40-
mn_i[i] = a_inv[rmq_min.query_idx(a[i - 1], a[i])];
41-
mx_i[i] = a_inv[rmq_max.query_idx(a[i - 1], a[i])];
40+
mn_i[i] = a_inv[rmq_min.idx(a[i - 1], a[i])];
41+
mx_i[i] = a_inv[rmq_max.idx(a[i - 1], a[i])];
4242
}
4343
}
4444
rep(i, 0, n) allocate(i, a[i], 1, 0, {});

tests/.config/.cppcheck_suppression_list

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,3 +62,4 @@ unusedFunction:../kactl/content/number-theory/ModPow.h:13
6262
unusedFunction:../kactl/stress-tests/utilities/genTree.h:49
6363
assertWithSideEffect:library_checker_aizu_tests/math/xor_basis_intersection.test.cpp:27
6464
assertWithSideEffect:library_checker_aizu_tests/math/xor_basis_intersection.test.cpp:36
65+
containerOutOfBounds:../library/data_structures/uncommon/permutation_tree.hpp:85

tests/library_checker_aizu_tests/data_structures/rmq_linear.test.cpp

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,21 +16,20 @@ int main() {
1616
while (q--) {
1717
int l, r;
1818
cin >> l >> r;
19-
int idx_right_min = rmq_less.query_idx(l, r - 1);
19+
int idx_right_min = rmq_less.idx(l, r - 1);
2020
assert(idx_right_min + 1 == r ||
2121
rmq_less.query(idx_right_min + 1, r - 1) >
2222
a[idx_right_min]);
2323
assert(l <= idx_right_min && idx_right_min < r);
2424
assert(rmq_less.query(l, r - 1) == a[idx_right_min]);
25-
assert(
26-
idx_right_min == rmq_greater.query_idx(l, r - 1));
27-
int idx_left_min = rmq_less_equal.query_idx(l, r - 1);
25+
assert(idx_right_min == rmq_greater.idx(l, r - 1));
26+
int idx_left_min = rmq_less_equal.idx(l, r - 1);
2827
assert(l == idx_left_min ||
2928
rmq_less_equal.query(l, idx_left_min - 1) >
3029
a[idx_left_min]);
3130
assert(l <= idx_left_min && idx_left_min < r);
32-
assert(idx_left_min ==
33-
rmq_greater_equal.query_idx(l, r - 1));
31+
assert(
32+
idx_left_min == rmq_greater_equal.idx(l, r - 1));
3433
assert(a[idx_right_min] == a[idx_left_min]);
3534
assert(idx_left_min <= idx_right_min);
3635
cout << a[idx_right_min] << '\n';

tests/library_checker_aizu_tests/handmade_tests/rmq_small_n.test.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ void test_all_subarrays(const vector<int>& a) {
1313
linear_rmq lin_rmq(a, less());
1414
for (int l = 0; l < n; l++) {
1515
for (int r = l + 1; r <= n; r++) {
16-
int idx_min = lin_rmq.query_idx(l, r - 1);
16+
int idx_min = lin_rmq.idx(l, r - 1);
1717
assert(l <= idx_min && idx_min < r);
1818
assert(a[idx_min] == rmq.query(l, r));
1919
assert(a[idx_min] == dis_rmq.query(l, r));

0 commit comments

Comments
 (0)