Skip to the content.

:warning: library/query/Mo.hpp

Depends on

Code

class Mo {
    int n;
    std::vector<std::pair<int, int>> lr;

  public:
    Mo() = default;
    Mo(const std::vector<std::pair<int, int>> &lr) : lr(lr) {
        for (const auto &[l, r] : lr) {
            assert(0 <= l and l <= r);
            n = std::max(n, r);
        }
    }
    void add(int l, int r) {
        assert(0 <= l and l <= r);
        lr.emplace_back(l, r);
        n = std::max(n, r);
    }

    template <typename AL, typename AR, typename EL, typename ER, typename F>
    void calc(const AL &add_left, const AR &add_right, const EL &erase_left,
              const ER &erase_right, const F &f) {
        int q = lr.size();
        int B = std::max(1, n / int(sqrt(q)));
        std::vector<int> ord(q);
        std::iota(ord.begin(), ord.end(), 0);
        std::ranges::sort(ord, [&](int a, int b) -> bool {
            int Ba = lr[a].first / B, Bb = lr[b].first / B;
            if (Ba != Bb)
                return Ba < Bb;
            return (Ba & 1) ^ (lr[a].second < lr[b].second);
        });
        int l = 0, r = 0;
        for (int idx : ord) {
            while (l > lr[idx].first)
                add_left(--l);
            while (r < lr[idx].second)
                add_right(r++);
            while (l < lr[idx].first)
                erase_left(l++);
            while (r > lr[idx].second)
                erase_right(--r);
            f(idx);
        }
    }

    template <typename A, typename E, typename F>
    void calc(const A &add, const E &erase, const F &f) {
        calc(add, add, erase, erase, f);
    }
};
#line 1 "library/query/Mo.hpp"
class Mo {
    int n;
    std::vector<std::pair<int, int>> lr;

  public:
    Mo() = default;
    Mo(const std::vector<std::pair<int, int>> &lr) : lr(lr) {
        for (const auto &[l, r] : lr) {
            assert(0 <= l and l <= r);
            n = std::max(n, r);
        }
    }
    void add(int l, int r) {
        assert(0 <= l and l <= r);
        lr.emplace_back(l, r);
        n = std::max(n, r);
    }

    template <typename AL, typename AR, typename EL, typename ER, typename F>
    void calc(const AL &add_left, const AR &add_right, const EL &erase_left,
              const ER &erase_right, const F &f) {
        int q = lr.size();
        int B = std::max(1, n / int(sqrt(q)));
        std::vector<int> ord(q);
        std::iota(ord.begin(), ord.end(), 0);
        std::ranges::sort(ord, [&](int a, int b) -> bool {
            int Ba = lr[a].first / B, Bb = lr[b].first / B;
            if (Ba != Bb)
                return Ba < Bb;
            return (Ba & 1) ^ (lr[a].second < lr[b].second);
        });
        int l = 0, r = 0;
        for (int idx : ord) {
            while (l > lr[idx].first)
                add_left(--l);
            while (r < lr[idx].second)
                add_right(r++);
            while (l < lr[idx].first)
                erase_left(l++);
            while (r > lr[idx].second)
                erase_right(--r);
            f(idx);
        }
    }

    template <typename A, typename E, typename F>
    void calc(const A &add, const E &erase, const F &f) {
        calc(add, add, erase, erase, f);
    }
};
Back to top page