#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