Range inversions query
(Mylib/Typical/range_inversions_query.cpp)
Operations
Requirements
Notes
Problems
References
Depends on
Verified with
Code
#pragma once
#include <algorithm>
#include <utility>
#include <vector>
#include "Mylib/Algorithm/mo_algorithm.cpp"
#include "Mylib/DataStructure/FenwickTree/fenwick_tree_add.cpp"
namespace haar_lib {
template <typename T>
class range_inversions_query {
std::vector<int> data_;
int N_;
std::vector<std::pair<int, int>> qs_;
public:
range_inversions_query() {}
range_inversions_query(std::vector<T> a) : N_(a.size()) {
auto b = a;
std::sort(b.begin(), b.end());
b.erase(std::unique(b.begin(), b.end()), b.end());
for (auto x : a) {
const int i = std::lower_bound(b.begin(), b.end(), x) - b.begin();
data_.push_back(i);
}
}
void add(int l, int r) { // [l, r)
qs_.emplace_back(l, r);
}
auto solve() {
const int Q = qs_.size();
fenwick_tree_add<int64_t> b(N_);
int64_t t = 0;
std::vector<int64_t> ans(Q);
auto append_left =
[&](int i) {
t += b.fold(0, data_[i]);
b.update(data_[i], 1);
};
auto append_right =
[&](int i) {
t += b.fold(data_[i] + 1, N_);
b.update(data_[i], 1);
};
auto remove_left =
[&](int i) {
t -= b.fold(0, data_[i]);
b.update(data_[i], -1);
};
auto remove_right =
[&](int i) {
t -= b.fold(data_[i] + 1, N_);
b.update(data_[i], -1);
};
auto query = [&](int i) { ans[i] = t; };
auto mo =
mo_algorithm(
N_, Q, append_left, append_right, remove_left, remove_right, query);
for (auto [l, r] : qs_) {
mo.add(l, r);
}
mo.run();
return ans;
}
};
} // namespace haar_lib
#line 2 "Mylib/Typical/range_inversions_query.cpp"
#include <algorithm>
#include <utility>
#include <vector>
#line 3 "Mylib/Algorithm/mo_algorithm.cpp"
#include <cassert>
#include <cmath>
#line 6 "Mylib/Algorithm/mo_algorithm.cpp"
namespace haar_lib {
template <typename AppendLeft, typename AppendRight, typename RemoveLeft, typename RemoveRight, typename Query>
class mo_algorithm {
int N_, Q_, index_, width_;
std::vector<int> left_, right_, ord_;
AppendLeft append_left_;
AppendRight append_right_;
RemoveLeft remove_left_;
RemoveRight remove_right_;
Query query_;
bool is_built_ = false;
public:
mo_algorithm() {}
mo_algorithm(
int N, int Q,
const AppendLeft &append_left, const AppendRight &append_right,
const RemoveLeft &remove_left, const RemoveRight &remove_right,
const Query &query) : N_(N), Q_(Q), index_(0), width_(std::sqrt(N)), left_(Q), right_(Q), ord_(Q), append_left_(append_left), append_right_(append_right), remove_left_(remove_left), remove_right_(remove_right), query_(query) {}
// [l, r)
void add(int l, int r) {
left_[index_] = l;
right_[index_] = r;
ord_[index_] = index_;
++index_;
}
void run() {
std::sort(
ord_.begin(), ord_.end(),
[&](int i, int j) {
const int a = left_[i] / width_, b = left_[j] / width_;
if (a == b) {
if (a & 1)
return right_[i] < right_[j];
else
return right_[i] > right_[j];
} else {
return a < b;
}
});
int q = 0;
int l = left_[ord_[0]], r = left_[ord_[0]];
for (int i = 0; i < Q_; ++i) {
int id = ord_[q++];
while (l != left_[id] or r != right_[id]) {
if (l > left_[id]) append_left_(--l);
if (l < left_[id]) remove_left_(l++);
if (r < right_[id]) append_right_(r++);
if (r > right_[id]) remove_right_(--r);
}
query_(id);
}
}
};
} // namespace haar_lib
#line 4 "Mylib/DataStructure/FenwickTree/fenwick_tree_add.cpp"
namespace haar_lib {
template <typename T>
class fenwick_tree_add {
public:
using value_type = T;
private:
int size_;
std::vector<value_type> data_;
public:
fenwick_tree_add() {}
fenwick_tree_add(int size) : size_(size), data_(size + 1, 0) {}
void update(int i, value_type val) {
assert(0 <= i and i < size_);
i += 1; // 1-index
while (i <= size_) {
data_[i] = data_[i] + val;
i += i & (-i);
}
}
value_type fold(int i) const { // [0, i)
assert(0 <= i and i <= size_);
value_type ret = 0;
while (i > 0) {
ret = ret + data_[i];
i -= i & (-i);
}
return ret;
}
value_type fold(int l, int r) const { // [l, r)
assert(0 <= l and l <= r and r <= size_);
return fold(r) - fold(l);
}
value_type operator[](int x) const {
return fold(x, x + 1);
}
};
} // namespace haar_lib
#line 7 "Mylib/Typical/range_inversions_query.cpp"
namespace haar_lib {
template <typename T>
class range_inversions_query {
std::vector<int> data_;
int N_;
std::vector<std::pair<int, int>> qs_;
public:
range_inversions_query() {}
range_inversions_query(std::vector<T> a) : N_(a.size()) {
auto b = a;
std::sort(b.begin(), b.end());
b.erase(std::unique(b.begin(), b.end()), b.end());
for (auto x : a) {
const int i = std::lower_bound(b.begin(), b.end(), x) - b.begin();
data_.push_back(i);
}
}
void add(int l, int r) { // [l, r)
qs_.emplace_back(l, r);
}
auto solve() {
const int Q = qs_.size();
fenwick_tree_add<int64_t> b(N_);
int64_t t = 0;
std::vector<int64_t> ans(Q);
auto append_left =
[&](int i) {
t += b.fold(0, data_[i]);
b.update(data_[i], 1);
};
auto append_right =
[&](int i) {
t += b.fold(data_[i] + 1, N_);
b.update(data_[i], 1);
};
auto remove_left =
[&](int i) {
t -= b.fold(0, data_[i]);
b.update(data_[i], -1);
};
auto remove_right =
[&](int i) {
t -= b.fold(data_[i] + 1, N_);
b.update(data_[i], -1);
};
auto query = [&](int i) { ans[i] = t; };
auto mo =
mo_algorithm(
N_, Q, append_left, append_right, remove_left, remove_right, query);
for (auto [l, r] : qs_) {
mo.add(l, r);
}
mo.run();
return ans;
}
};
} // namespace haar_lib
Back to top page