Library

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

View the Project on GitHub ret2home/Library

:heavy_check_mark: Lazy Segment Tree
(structure/SegmentTree.cpp)

概要

モノイドについて、区間に対する処理を高速に行えるデータ構造。

結合律が成立し、かつ単位元が存在するならモノイドだと思って OK (Minimum や Sum など)。

型は Segtree<Monoid,OperatorMonoid,F,G,H> のように書く(詳細はTestのソースコード)。 F は要素同士の、G は要素と作用素、H は作用素同士の二項演算。

計算量

Depends on

Verified with

Code

#pragma once
#include "../template/template.cpp"

template <typename Monoid,
          typename OperatorMonoid,
          Monoid (*f)(Monoid, Monoid, int),
          Monoid (*g)(Monoid, OperatorMonoid, int),
          OperatorMonoid (*h)(OperatorMonoid, OperatorMonoid, int)>
struct Segtree {
    int size = 1;

   private:
    vector<Monoid> dat;
    vector<OperatorMonoid> lazy;
    Monoid M;
    OperatorMonoid OM;

   public:
    void eval(int k, int l, int r) {
        if (lazy[k] != OM) {
            dat[k] = g(dat[k], lazy[k], r - l);
            if (r - l > 1) {
                lazy[(k << 1) + 1] = h(lazy[(k << 1) + 1], lazy[k], r - l);
                lazy[(k << 1) + 2] = h(lazy[(k << 1) + 2], lazy[k], r - l);
            }
            lazy[k] = OM;
        }
    }
    void update(int a, int b, OperatorMonoid M, int k = 0, int l = 0, int r = -1) {
        if (r == -1) r = size;
        eval(k, l, r);
        if (r <= a || b <= l) return;
        if (a <= l && r <= b) {
            lazy[k] = h(lazy[k], M, r - l);
            eval(k, l, r);
            return;
        }
        update(a, b, M, (k << 1) + 1, l, (l + r) >> 1);
        update(a, b, M, (k << 1) + 2, (l + r) >> 1, r);
        dat[k] = f(dat[(k << 1) + 1], dat[(k << 1) + 2], r - l);
    }
    Monoid query(int a, int b, int k = 0, int l = 0, int r = -1) {
        if (r == -1) r = size;
        eval(k, l, r);
        if (r <= a || b <= l) return M;
        if (a <= l && r <= b) return dat[k];
        Monoid lv = query(a, b, (k << 1) + 1, l, (l + r) >> 1);
        Monoid rv = query(a, b, (k << 1) + 2, (l + r) >> 1, r);
        return f(lv, rv, r - l);
    }
    template <class C>
    int minLeft(int a, int b, C &check, Monoid x, int k = 0, int l = 0, int r = -1) {
        if (r == -1) r = size;
        eval(k, l, r);
        if (r <= a || b <= l || !check(dat[k], x)) return -1;
        if (r - l == 1) return l;
        int lv = minLeft(a, b, check, x, (k << 1) + 1, l, (l + r) >> 1);
        if (lv != -1) return lv;
        return minLeft(a, b, check, x, (k << 1) + 2, (l + r) >> 1, r);
    }
    template <class C>
    int maxRight(int a, int b, C &check, Monoid x, int k = 0, int l = 0, int r = -1) {
        if (r == -1) r = size;
        eval(k, l, r);
        if (r <= a || b <= l || !check(dat[k], x)) return -1;
        if (r - l == 1) return l;
        int rv = maxRight(a, b, check, x, (k << 1) + 2, (l + r) >> 1, r);
        if (rv != -1) return rv;
        return maxRight(a, b, check, x, (k << 1) + 1, l, (l + r) >> 1);
    }
    void set(int a, Monoid x) {
        dat[a + size - 1] = x;
    }
    void init(int k = 0, int l = 0, int r = -1) {
        if (r == -1) r = size;
        if (r - l == 1) return;
        init((k << 1) + 1, l, (l + r) >> 1);
        init((k << 1) + 2, (l + r) >> 1, r);
        dat[k] = f(dat[k * 2 + 1], dat[k * 2 + 2], r - l);
    }
    Segtree(int x, Monoid M, OperatorMonoid OM)
        : M(M), OM(OM) {
        while (size < x) size <<= 1;
        dat.resize((size << 1) - 1, M);
        lazy.resize((size << 1) - 1, OM);
    }
};

/*
@brief Lazy Segment Tree
@docs docs/SegmentTree.md
*/
#line 2 "template/template.cpp"
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define rep(i, n) for (int i = 0; i < n; i++)
#define REP(i, n) for (int i = 1; i < n; i++)
#define rev(i, n) for (int i = n - 1; i >= 0; i--)
#define REV(i, n) for (int i = n - 1; i > 0; i--)
#define all(v) v.begin(), v.end()
#define PL pair<ll, ll>
#define PI pair<int, int>
#define pi acos(-1)
#define len(s) (int)s.size()
#define compress(v) \
    sort(all(v));   \
    v.erase(unique(all(v)), v.end());
#define comid(v, x) lower_bound(all(v), x) - v.begin()

template<class T>
using prique=priority_queue<T,vector<T>,greater<>>;

template <class T, class U>
inline bool chmin(T &a, U b) {
    if (a > b) {
        a = b;
        return true;
    }
    return false;
}
template <class T, class U>
inline bool chmax(T &a, U b) {
    if (a < b) {
        a = b;
        return true;
    }
    return false;
}
constexpr ll inf = 3e18;
#line 3 "structure/SegmentTree.cpp"

template <typename Monoid,
          typename OperatorMonoid,
          Monoid (*f)(Monoid, Monoid, int),
          Monoid (*g)(Monoid, OperatorMonoid, int),
          OperatorMonoid (*h)(OperatorMonoid, OperatorMonoid, int)>
struct Segtree {
    int size = 1;

   private:
    vector<Monoid> dat;
    vector<OperatorMonoid> lazy;
    Monoid M;
    OperatorMonoid OM;

   public:
    void eval(int k, int l, int r) {
        if (lazy[k] != OM) {
            dat[k] = g(dat[k], lazy[k], r - l);
            if (r - l > 1) {
                lazy[(k << 1) + 1] = h(lazy[(k << 1) + 1], lazy[k], r - l);
                lazy[(k << 1) + 2] = h(lazy[(k << 1) + 2], lazy[k], r - l);
            }
            lazy[k] = OM;
        }
    }
    void update(int a, int b, OperatorMonoid M, int k = 0, int l = 0, int r = -1) {
        if (r == -1) r = size;
        eval(k, l, r);
        if (r <= a || b <= l) return;
        if (a <= l && r <= b) {
            lazy[k] = h(lazy[k], M, r - l);
            eval(k, l, r);
            return;
        }
        update(a, b, M, (k << 1) + 1, l, (l + r) >> 1);
        update(a, b, M, (k << 1) + 2, (l + r) >> 1, r);
        dat[k] = f(dat[(k << 1) + 1], dat[(k << 1) + 2], r - l);
    }
    Monoid query(int a, int b, int k = 0, int l = 0, int r = -1) {
        if (r == -1) r = size;
        eval(k, l, r);
        if (r <= a || b <= l) return M;
        if (a <= l && r <= b) return dat[k];
        Monoid lv = query(a, b, (k << 1) + 1, l, (l + r) >> 1);
        Monoid rv = query(a, b, (k << 1) + 2, (l + r) >> 1, r);
        return f(lv, rv, r - l);
    }
    template <class C>
    int minLeft(int a, int b, C &check, Monoid x, int k = 0, int l = 0, int r = -1) {
        if (r == -1) r = size;
        eval(k, l, r);
        if (r <= a || b <= l || !check(dat[k], x)) return -1;
        if (r - l == 1) return l;
        int lv = minLeft(a, b, check, x, (k << 1) + 1, l, (l + r) >> 1);
        if (lv != -1) return lv;
        return minLeft(a, b, check, x, (k << 1) + 2, (l + r) >> 1, r);
    }
    template <class C>
    int maxRight(int a, int b, C &check, Monoid x, int k = 0, int l = 0, int r = -1) {
        if (r == -1) r = size;
        eval(k, l, r);
        if (r <= a || b <= l || !check(dat[k], x)) return -1;
        if (r - l == 1) return l;
        int rv = maxRight(a, b, check, x, (k << 1) + 2, (l + r) >> 1, r);
        if (rv != -1) return rv;
        return maxRight(a, b, check, x, (k << 1) + 1, l, (l + r) >> 1);
    }
    void set(int a, Monoid x) {
        dat[a + size - 1] = x;
    }
    void init(int k = 0, int l = 0, int r = -1) {
        if (r == -1) r = size;
        if (r - l == 1) return;
        init((k << 1) + 1, l, (l + r) >> 1);
        init((k << 1) + 2, (l + r) >> 1, r);
        dat[k] = f(dat[k * 2 + 1], dat[k * 2 + 2], r - l);
    }
    Segtree(int x, Monoid M, OperatorMonoid OM)
        : M(M), OM(OM) {
        while (size < x) size <<= 1;
        dat.resize((size << 1) - 1, M);
        lazy.resize((size << 1) - 1, OM);
    }
};

/*
@brief Lazy Segment Tree
@docs docs/SegmentTree.md
*/
Back to top page