cplib-cpp

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

View the Project on GitHub hitonanode/cplib-cpp

:heavy_check_mark: segmenttree/range-update-range-get.hpp

Verified with

Code

#pragma once
#include <algorithm>
#include <iostream>
#include <tuple>
#include <vector>

// CUT begin
template <typename TDATA, typename TLAZY, typename TRET, typename TQUERY> struct LazySegmentTree {
    TLAZY zero_lazy;
    TRET zero_ret;
    int N;
    int head;
    std::vector<TDATA> data;
    std::vector<TLAZY> lazy;

    // Here, you have to calculate data[pos] from children (data[l], data[r]),
    // Assumptions: `lazy[pos] = lazy[l] = lazy[r] = zero_lazy`
    virtual void merge_data(int pos) = 0;

    // Here, you must propagate lazy[pos] and update data[pos] by reflecting lazy[pos], without
    // inconsistency After this, lazy[pos] must be zero_lazy.
    virtual void reflect_lazy(int pos) = 0;

    // operate d to lazy[pos] (merge two TLAZY's)
    virtual void overlap_lazy(int pos, const TLAZY &d) = 0;

    // Assumption: `lazy[pos] = zero_lazy`
    virtual TRET data2ret(int pos, const TQUERY &query) = 0;

    virtual TRET merge_ret(const TRET &l, const TRET &r, const TQUERY &query) = 0;

    ////// general description //////
    LazySegmentTree() = default;
    void initialize(const std::vector<TDATA> &data_init, const TDATA &zero_data,
                    const TLAZY &zero_lazy_, const TRET &zero_ret_) {
        N = data_init.size();
        head = 1;
        while (head < N) head <<= 1;
        zero_lazy = zero_lazy_;
        zero_ret = zero_ret_;
        data.assign(head * 2, zero_data);
        lazy.assign(head * 2, zero_lazy);
        std::copy(data_init.begin(), data_init.end(), data.begin() + head);
        for (int pos = head; --pos;) merge_data(pos);
    }

    void _update(int begin, int end, const TLAZY &delay, int pos, int l, int r) {
        // Operate `delay` to the node pos
        // After this, lazy[pos] MUST be zero so that merge_data() works correctly
        if (begin <= l and r <= end) { // Update whole [l, r) by delay
            overlap_lazy(pos, delay);
            reflect_lazy(pos);
        } else if (begin < r and l < end) { // Update somewhere in [l, r)
            reflect_lazy(pos);
            _update(begin, end, delay, pos * 2, l, (l + r) / 2);
            _update(begin, end, delay, pos * 2 + 1, (l + r) / 2, r);
            merge_data(pos);
        } else
            reflect_lazy(pos);
    }

    void update(int begin, int end, const TLAZY &delay) { _update(begin, end, delay, 1, 0, head); }

    TRET _get(int begin, int end, int pos, int l, int r,
              const TQUERY &query) // Get value in [begin, end)
    {
        reflect_lazy(pos);
        if (begin <= l and r <= end)
            return data2ret(pos, query);
        else if (begin < r and l < end) {
            TRET vl = _get(begin, end, pos * 2, l, (l + r) / 2, query);
            TRET vr = _get(begin, end, pos * 2 + 1, (l + r) / 2, r, query);
            return merge_ret(vl, vr, query);
        } else
            return zero_ret;
    }
    TRET get(int begin, int end, const TQUERY &query = NULL) {
        return _get(begin, end, 1, 0, head, query);
    }
};

// Range Update & Range Sum
// - get(l, r): return x_l + ... + x_{r - 1}
// - update(l, r, val): x_l, ..., x_{r - 1} <- val
template <typename T>
struct RangeUpdateRangeSum
    : public LazySegmentTree<std::pair<T, size_t>, std::pair<T, bool>, T, std::tuple<>> {
    using TDATA = std::pair<T, size_t>;
    using TLAZY = std::pair<T, bool>;
    using SegTree = LazySegmentTree<TDATA, TLAZY, T, std::tuple<>>;
    using SegTree::data;
    using SegTree::lazy;
    void merge_data(int i) override {
        data[i] = std::make_pair(data[i * 2].first + data[i * 2 + 1].first,
                                 data[i * 2].second + data[i * 2 + 1].second);
    };
    void reflect_lazy(int i) override {
        if (lazy[i].second) {
            if (i < SegTree::head) overlap_lazy(i * 2, lazy[i]), overlap_lazy(i * 2 + 1, lazy[i]);
            data[i].first = lazy[i].first * data[i].second;
        }
        lazy[i].second = false;
    }
    void overlap_lazy(int i, const TLAZY &p) override {
        if (p.second) lazy[i] = p;
    }
    T data2ret(int i, const std::tuple<> &) override { return data[i].first; }
    T merge_ret(const T &l, const T &r, const std::tuple<> &) override { return l + r; }
    void update(int l, int r, T val) { SegTree::update(l, r, TLAZY(val, true)); }
    T get(int l, int r) { return SegTree::get(l, r, {}); }
    RangeUpdateRangeSum(const std::vector<T> &seq) : SegTree::LazySegmentTree() {
        std::vector<TDATA> vec;
        for (const auto &x : seq) vec.emplace_back(x, 1);
        SegTree::initialize(vec, TDATA(0, 0), TLAZY(0, false), 0);
    }
};
#line 2 "segmenttree/range-update-range-get.hpp"
#include <algorithm>
#include <iostream>
#include <tuple>
#include <vector>

// CUT begin
template <typename TDATA, typename TLAZY, typename TRET, typename TQUERY> struct LazySegmentTree {
    TLAZY zero_lazy;
    TRET zero_ret;
    int N;
    int head;
    std::vector<TDATA> data;
    std::vector<TLAZY> lazy;

    // Here, you have to calculate data[pos] from children (data[l], data[r]),
    // Assumptions: `lazy[pos] = lazy[l] = lazy[r] = zero_lazy`
    virtual void merge_data(int pos) = 0;

    // Here, you must propagate lazy[pos] and update data[pos] by reflecting lazy[pos], without
    // inconsistency After this, lazy[pos] must be zero_lazy.
    virtual void reflect_lazy(int pos) = 0;

    // operate d to lazy[pos] (merge two TLAZY's)
    virtual void overlap_lazy(int pos, const TLAZY &d) = 0;

    // Assumption: `lazy[pos] = zero_lazy`
    virtual TRET data2ret(int pos, const TQUERY &query) = 0;

    virtual TRET merge_ret(const TRET &l, const TRET &r, const TQUERY &query) = 0;

    ////// general description //////
    LazySegmentTree() = default;
    void initialize(const std::vector<TDATA> &data_init, const TDATA &zero_data,
                    const TLAZY &zero_lazy_, const TRET &zero_ret_) {
        N = data_init.size();
        head = 1;
        while (head < N) head <<= 1;
        zero_lazy = zero_lazy_;
        zero_ret = zero_ret_;
        data.assign(head * 2, zero_data);
        lazy.assign(head * 2, zero_lazy);
        std::copy(data_init.begin(), data_init.end(), data.begin() + head);
        for (int pos = head; --pos;) merge_data(pos);
    }

    void _update(int begin, int end, const TLAZY &delay, int pos, int l, int r) {
        // Operate `delay` to the node pos
        // After this, lazy[pos] MUST be zero so that merge_data() works correctly
        if (begin <= l and r <= end) { // Update whole [l, r) by delay
            overlap_lazy(pos, delay);
            reflect_lazy(pos);
        } else if (begin < r and l < end) { // Update somewhere in [l, r)
            reflect_lazy(pos);
            _update(begin, end, delay, pos * 2, l, (l + r) / 2);
            _update(begin, end, delay, pos * 2 + 1, (l + r) / 2, r);
            merge_data(pos);
        } else
            reflect_lazy(pos);
    }

    void update(int begin, int end, const TLAZY &delay) { _update(begin, end, delay, 1, 0, head); }

    TRET _get(int begin, int end, int pos, int l, int r,
              const TQUERY &query) // Get value in [begin, end)
    {
        reflect_lazy(pos);
        if (begin <= l and r <= end)
            return data2ret(pos, query);
        else if (begin < r and l < end) {
            TRET vl = _get(begin, end, pos * 2, l, (l + r) / 2, query);
            TRET vr = _get(begin, end, pos * 2 + 1, (l + r) / 2, r, query);
            return merge_ret(vl, vr, query);
        } else
            return zero_ret;
    }
    TRET get(int begin, int end, const TQUERY &query = NULL) {
        return _get(begin, end, 1, 0, head, query);
    }
};

// Range Update & Range Sum
// - get(l, r): return x_l + ... + x_{r - 1}
// - update(l, r, val): x_l, ..., x_{r - 1} <- val
template <typename T>
struct RangeUpdateRangeSum
    : public LazySegmentTree<std::pair<T, size_t>, std::pair<T, bool>, T, std::tuple<>> {
    using TDATA = std::pair<T, size_t>;
    using TLAZY = std::pair<T, bool>;
    using SegTree = LazySegmentTree<TDATA, TLAZY, T, std::tuple<>>;
    using SegTree::data;
    using SegTree::lazy;
    void merge_data(int i) override {
        data[i] = std::make_pair(data[i * 2].first + data[i * 2 + 1].first,
                                 data[i * 2].second + data[i * 2 + 1].second);
    };
    void reflect_lazy(int i) override {
        if (lazy[i].second) {
            if (i < SegTree::head) overlap_lazy(i * 2, lazy[i]), overlap_lazy(i * 2 + 1, lazy[i]);
            data[i].first = lazy[i].first * data[i].second;
        }
        lazy[i].second = false;
    }
    void overlap_lazy(int i, const TLAZY &p) override {
        if (p.second) lazy[i] = p;
    }
    T data2ret(int i, const std::tuple<> &) override { return data[i].first; }
    T merge_ret(const T &l, const T &r, const std::tuple<> &) override { return l + r; }
    void update(int l, int r, T val) { SegTree::update(l, r, TLAZY(val, true)); }
    T get(int l, int r) { return SegTree::get(l, r, {}); }
    RangeUpdateRangeSum(const std::vector<T> &seq) : SegTree::LazySegmentTree() {
        std::vector<TDATA> vec;
        for (const auto &x : seq) vec.emplace_back(x, 1);
        SegTree::initialize(vec, TDATA(0, 0), TLAZY(0, false), 0);
    }
};
Back to top page