This documentation is automatically generated by online-judge-tools/verification-helper
モノイドについて、区間に対する処理を高速に行えるデータ構造。
結合律が成立し、かつ単位元が存在するならモノイドだと思って OK (Minimum や Sum など)。
型は Segtree<Monoid,OperatorMonoid,F,G,H>
のように書く(詳細はTestのソースコード)。
F
は要素同士の、G
は要素と作用素、H
は作用素同士の二項演算。
Segtree(N,M,OM)
要素数 N
, 要素の単位元 M
, 作用素の単位元 OM
で初期化するupdate(a,b,x)
: [a,b)
に対して 作用素 x
を適用query(a,b)
: [a,b)
の演算の結果minLeft(a,b,C,x)
: [a,b)
で C(要素,x)
を満たす最小の indexmaxRight(a,b,C,x)
: [a,b)
で C(要素,x)
を満たす最大の index#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
*/