kyopro-lib

This documentation is automatically generated by online-judge-tools/verification-helper

View on GitHub

:x: 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