Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 9 additions & 9 deletions .verify-helper/timestamps.remote.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,15 @@
"tests/library_checker_aizu_tests/data_structures/line_tree_lib_checker.test.cpp": "2025-02-10 23:30:47 -0700",
"tests/library_checker_aizu_tests/data_structures/merge_sort_tree.test.cpp": "2025-02-11 13:53:30 -0700",
"tests/library_checker_aizu_tests/data_structures/mode_query.test.cpp": "2025-02-10 23:30:47 -0700",
"tests/library_checker_aizu_tests/data_structures/permutation_tree.test.cpp": "2025-06-03 13:37:20 -0600",
"tests/library_checker_aizu_tests/data_structures/permutation_tree.test.cpp": "2025-08-03 18:39:58 -0600",
"tests/library_checker_aizu_tests/data_structures/persistent_queue_tree.test.cpp": "2025-02-10 14:50:36 -0700",
"tests/library_checker_aizu_tests/data_structures/persistent_seg_tree.test.cpp": "2024-12-05 10:41:42 -0600",
"tests/library_checker_aizu_tests/data_structures/pq_ds_undo_sliding_window.test.cpp": "2025-02-10 14:50:36 -0700",
"tests/library_checker_aizu_tests/data_structures/pq_ds_undo_with_dsu.test.cpp": "2025-02-10 14:50:36 -0700",
"tests/library_checker_aizu_tests/data_structures/range_parallel_dsu.test.cpp": "2025-02-10 23:30:47 -0700",
"tests/library_checker_aizu_tests/data_structures/rmq_disjoint_sparse_table.test.cpp": "2024-12-15 14:34:10 -0600",
"tests/library_checker_aizu_tests/data_structures/rmq_linear.test.cpp": "2025-06-03 13:37:20 -0600",
"tests/library_checker_aizu_tests/data_structures/rmq_sparse_table.test.cpp": "2025-06-03 13:37:20 -0600",
"tests/library_checker_aizu_tests/data_structures/rmq_linear.test.cpp": "2025-08-03 18:39:58 -0600",
"tests/library_checker_aizu_tests/data_structures/rmq_sparse_table.test.cpp": "2025-08-03 18:39:58 -0600",
"tests/library_checker_aizu_tests/data_structures/rmq_sparse_table_inc.test.cpp": "2024-12-15 14:34:10 -0600",
"tests/library_checker_aizu_tests/data_structures/simple_tree.test.cpp": "2024-12-14 15:47:13 -0600",
"tests/library_checker_aizu_tests/data_structures/simple_tree_inc.test.cpp": "2024-12-21 00:23:10 -0500",
Expand Down Expand Up @@ -78,8 +78,8 @@
"tests/library_checker_aizu_tests/handmade_tests/mobius.test.cpp": "2025-02-10 14:50:36 -0700",
"tests/library_checker_aizu_tests/handmade_tests/mod_int.test.cpp": "2024-12-14 19:50:29 -0600",
"tests/library_checker_aizu_tests/handmade_tests/n_choose_k.test.cpp": "2025-01-15 00:22:31 -0700",
"tests/library_checker_aizu_tests/handmade_tests/permutation_tree_small.test.cpp": "2025-06-03 13:37:20 -0600",
"tests/library_checker_aizu_tests/handmade_tests/rmq_small_n.test.cpp": "2025-06-03 13:37:20 -0600",
"tests/library_checker_aizu_tests/handmade_tests/permutation_tree_small.test.cpp": "2025-08-03 18:39:58 -0600",
"tests/library_checker_aizu_tests/handmade_tests/rmq_small_n.test.cpp": "2025-08-03 18:39:58 -0600",
"tests/library_checker_aizu_tests/handmade_tests/sa_find_subarray.test.cpp": "2025-02-10 14:50:36 -0700",
"tests/library_checker_aizu_tests/handmade_tests/seg_tree_find.test.cpp": "2024-12-14 19:50:29 -0600",
"tests/library_checker_aizu_tests/handmade_tests/seg_tree_find_small.test.cpp": "2024-12-14 19:50:29 -0600",
Expand Down Expand Up @@ -107,9 +107,9 @@
"tests/library_checker_aizu_tests/math/xor_basis.test.cpp": "2025-04-22 21:37:22 -0500",
"tests/library_checker_aizu_tests/math/xor_basis_intersection.test.cpp": "2025-02-10 23:30:47 -0700",
"tests/library_checker_aizu_tests/monotonic_stack_related/cartesian_binary_tree.test.cpp": "2025-02-10 14:50:36 -0700",
"tests/library_checker_aizu_tests/monotonic_stack_related/cartesian_k_ary_tree.test.cpp": "2025-06-03 13:37:20 -0600",
"tests/library_checker_aizu_tests/monotonic_stack_related/count_rectangles.test.cpp": "2025-06-03 13:37:20 -0600",
"tests/library_checker_aizu_tests/monotonic_stack_related/max_rect_histogram.test.cpp": "2025-06-03 13:37:20 -0600",
"tests/library_checker_aizu_tests/monotonic_stack_related/cartesian_k_ary_tree.test.cpp": "2025-08-03 18:39:58 -0600",
"tests/library_checker_aizu_tests/monotonic_stack_related/count_rectangles.test.cpp": "2025-08-03 18:39:58 -0600",
"tests/library_checker_aizu_tests/monotonic_stack_related/max_rect_histogram.test.cpp": "2025-08-03 18:39:58 -0600",
"tests/library_checker_aizu_tests/strings/kmp.test.cpp": "2024-12-14 19:50:29 -0600",
"tests/library_checker_aizu_tests/strings/lcp_array.test.cpp": "2025-02-10 14:50:36 -0700",
"tests/library_checker_aizu_tests/strings/lcp_query_palindrome.test.cpp": "2025-02-10 14:50:36 -0700",
Expand All @@ -123,7 +123,7 @@
"tests/library_checker_aizu_tests/strings/sa_cmp.test.cpp": "2025-02-10 14:50:36 -0700",
"tests/library_checker_aizu_tests/strings/sa_sort_pairs.test.cpp": "2025-02-10 14:50:36 -0700",
"tests/library_checker_aizu_tests/strings/single_matching_bs.test.cpp": "2025-02-10 14:50:36 -0700",
"tests/library_checker_aizu_tests/strings/suffix_array.test.cpp": "2025-06-03 13:37:20 -0600",
"tests/library_checker_aizu_tests/strings/suffix_array.test.cpp": "2025-08-03 18:39:58 -0600",
"tests/library_checker_aizu_tests/strings/suffix_array_short.test.cpp": "2025-02-10 14:50:36 -0700",
"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",
Expand Down
52 changes: 25 additions & 27 deletions library/data_structures/uncommon/linear_rmq.hpp
Original file line number Diff line number Diff line change
@@ -1,49 +1,47 @@
#pragma once
//! https://codeforces.com/blog/entry/125371?#comment-1173604
//! @code
//! linear_rmq rmq1(a, less());//right-most min
//! linear_rmq rmq2(a, less_equal());//left-most min
//! linear_rmq rmq3(a, greater());//right-most max
//! linear_rmq rmq4(a, greater_equal());//left-most max
//! linear_rmq rmq1(a, less()); //right-most min
//! linear_rmq rmq2(a, less_equal()); //left-most min
//! linear_rmq rmq3(a, greater()); //right-most max
//! linear_rmq rmq4(a, greater_equal()); //left-most max
//! linear_rmq rmq5(a, [&](auto& x, auto& y) {
//! return x < y;
//! });
//! @endcode
//! @time O(n + q)
//! @space O(n)
template<class T, class F> struct linear_rmq {
int n;
vector<T> a;
F cmp;
vi head;
vector<array<int, 2>> t;
vi in, asc, head;
linear_rmq(const vector<T>& a, F cmp):
a(a), cmp(cmp), head(sz(a) + 1), t(sz(a)) {
n(sz(a)), a(a), cmp(cmp), in(n), asc(n), head(n + 1) {
vi st{-1};
for (int i = 0; i <= sz(a); i++) {
int prev = -1;
while (st.back() != -1 &&
(i == sz(a) || !cmp(a[st.back()], a[i]))) {
if (prev != -1) head[prev] = st.back();
int pw2 = 1 << __lg((end(st)[-2] + 1) ^ i);
t[st.back()][0] = prev = i & -pw2;
rep(i, 0, n + 1) {
int prev = 0;
while (sz(st) > 1 &&
(i == n || !cmp(a[st.back()], a[i]))) {
head[prev] = st.back();
auto k = end(st)[-2] + 1u, b = bit_floor(k ^ i);
in[st.back()] = prev = i & -b, asc[k] |= b;
st.pop_back();
t[st.back() + 1][1] |= pw2;
}
if (prev != -1) head[prev] = i;
st.push_back(i);
st.push_back(head[prev] = i);
}
rep(i, 1, sz(a)) t[i][1] =
(t[i][1] | t[i - 1][1]) & -(t[i][0] & -t[i][0]);
rep(i, 1, n) asc[i] =
(asc[i] | asc[i - 1]) & -(in[i] & -in[i]);
}
int query_idx(int l, int r) { // [l, r]
if (unsigned j = t[l][0] ^ t[r][0]; j) {
j = t[l][1] & t[r][1] & -bit_floor(j);
if (unsigned k = t[l][1] ^ j; k)
k = bit_floor(k), l = head[(t[l][0] & -k) | k];
if (unsigned k = t[r][1] ^ j; k)
k = bit_floor(k), r = head[(t[r][0] & -k) | k];
int idx(int l, int r) { // [l, r]
if (unsigned j = in[l] ^ in[r]; j) {
j = asc[l] & asc[r] & -bit_floor(j);
if (unsigned k = asc[l] ^ j; k)
k = bit_floor(k), l = head[(in[l] & -k) | k];
if (unsigned k = asc[r] ^ j; k)
k = bit_floor(k), r = head[(in[r] & -k) | k];
}
return cmp(a[l], a[r]) ? l : r;
}
T query(int l, int r) { return a[query_idx(l, r)]; }
T query(int l, int r) { return a[idx(l, r)]; }
};
4 changes: 2 additions & 2 deletions library/data_structures/uncommon/permutation_tree.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ struct perm_tree {
linear_rmq rmq_min(a_inv, less());
linear_rmq rmq_max(a_inv, greater());
rep(i, 1, n) {
mn_i[i] = a_inv[rmq_min.query_idx(a[i - 1], a[i])];
mx_i[i] = a_inv[rmq_max.query_idx(a[i - 1], a[i])];
mn_i[i] = a_inv[rmq_min.idx(a[i - 1], a[i])];
mx_i[i] = a_inv[rmq_max.idx(a[i - 1], a[i])];
}
}
rep(i, 0, n) allocate(i, a[i], 1, 0, {});
Expand Down
1 change: 1 addition & 0 deletions tests/.config/.cppcheck_suppression_list
Original file line number Diff line number Diff line change
Expand Up @@ -62,3 +62,4 @@ unusedFunction:../kactl/content/number-theory/ModPow.h:13
unusedFunction:../kactl/stress-tests/utilities/genTree.h:49
assertWithSideEffect:library_checker_aizu_tests/math/xor_basis_intersection.test.cpp:27
assertWithSideEffect:library_checker_aizu_tests/math/xor_basis_intersection.test.cpp:36
containerOutOfBounds:../library/data_structures/uncommon/permutation_tree.hpp:85
Original file line number Diff line number Diff line change
Expand Up @@ -16,21 +16,20 @@ int main() {
while (q--) {
int l, r;
cin >> l >> r;
int idx_right_min = rmq_less.query_idx(l, r - 1);
int idx_right_min = rmq_less.idx(l, r - 1);
assert(idx_right_min + 1 == r ||
rmq_less.query(idx_right_min + 1, r - 1) >
a[idx_right_min]);
assert(l <= idx_right_min && idx_right_min < r);
assert(rmq_less.query(l, r - 1) == a[idx_right_min]);
assert(
idx_right_min == rmq_greater.query_idx(l, r - 1));
int idx_left_min = rmq_less_equal.query_idx(l, r - 1);
assert(idx_right_min == rmq_greater.idx(l, r - 1));
int idx_left_min = rmq_less_equal.idx(l, r - 1);
assert(l == idx_left_min ||
rmq_less_equal.query(l, idx_left_min - 1) >
a[idx_left_min]);
assert(l <= idx_left_min && idx_left_min < r);
assert(idx_left_min ==
rmq_greater_equal.query_idx(l, r - 1));
assert(
idx_left_min == rmq_greater_equal.idx(l, r - 1));
assert(a[idx_right_min] == a[idx_left_min]);
assert(idx_left_min <= idx_right_min);
cout << a[idx_right_min] << '\n';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ void test_all_subarrays(const vector<int>& a) {
linear_rmq lin_rmq(a, less());
for (int l = 0; l < n; l++) {
for (int r = l + 1; r <= n; r++) {
int idx_min = lin_rmq.query_idx(l, r - 1);
int idx_min = lin_rmq.idx(l, r - 1);
assert(l <= idx_min && idx_min < r);
assert(a[idx_min] == rmq.query(l, r));
assert(a[idx_min] == dis_rmq.query(l, r));
Expand Down
Loading