12template <
typename Range,
typename Element>
13inline constexpr bool is_static_query_range_v = std::is_invocable_v<
decltype(&Range::push_front), Range&, Element> &&
14 std::is_invocable_v<
decltype(&Range::pop_front), Range&, Element> &&
15 std::is_invocable_v<
decltype(&Range::push_back), Range&, Element> &&
16 std::is_invocable_v<
decltype(&Range::pop_back), Range&, Element> &&
17 std::is_invocable_v<
decltype(&Range::get), Range&>;
36template <
typename RandomIt,
typename Range,
37 std::enable_if_t<impl::is_static_query_range_v<Range, typename std::iterator_traits<RandomIt>::value_type>>* =
40 Range& range,
const std::vector<std::pair<RandomIt, RandomIt>>& queries) {
41 if (queries.empty()) {
44 std::vector<size_t> order(queries.size());
45 std::iota(order.begin(), order.end(), 0);
46 std::sort(order.begin(), order.end(), [&](
size_t i,
size_t j) { return queries[i].first < queries[j].first; });
47 auto leftmost = std::min_element(queries.begin(), queries.end(), [](
const auto& a,
const auto& b) {
48 return a.first < b.first;
50 auto rightmost = std::max_element(queries.begin(), queries.end(), [](
const auto& a,
const auto& b) {
51 return a.second < b.second;
53 size_t block_size = std::max(
size_t(1),
size_t((rightmost - leftmost) / std::sqrt(queries.size())));
54 bool block_reverse =
false;
55 auto block_sort_cmp = [&](
size_t i,
size_t j) {
56 return block_reverse ? queries[i].second > queries[j].second : queries[i].second < queries[j].second;
58 auto block_begin = order.begin();
59 for (
auto block_end = block_begin; block_end < order.end(); block_end++) {
60 if (queries[*block_end].first - queries[*block_begin].first >= block_size) {
61 std::sort(block_begin, block_end, block_sort_cmp);
63 block_begin = block_end;
66 std::sort(block_begin, order.end(), block_sort_cmp);
67 RandomIt l = queries[order[0]].first, r = l;
68 std::vector<decltype(std::declval<Range>().get())> ans(queries.size());
69 for (
auto i : order) {
70 auto [l_target, r_target] = queries[i];
71 while (l > l_target) {
72 range.push_front(*(--l));
74 while (r < r_target) {
75 range.push_back(*(r++));
77 while (l < l_target) {
78 range.pop_front(*(l++));
80 while (r > r_target) {
81 range.pop_back(*(--r));
std::vector< decltype(std::declval< Range >().get())> batch_range_queries(Range &range, const std::vector< std::pair< RandomIt, RandomIt > > &queries)
Batch range queries using Mo's algorithm.
Definition: batch_range_queries.hpp:39