template< typename Monoid >
struct SegmentTree {
using F = function< Monoid(Monoid, Monoid) >; //max, minなど
int sz; //一番下の段以外
vector< Monoid > seg; //値が入る
const F f; //関数
const Monoid M1; //int_max
//size、 関数、 int_max
SegmentTree(int n, const F f, const Monoid& M1) : f(f), M1(M1) {//f,M1を(private関数)に
sz = 1;
while (sz < n) sz <<= 1; //木の大きさ
seg.assign(2 * sz, M1); //M1で初期化
}
void set(int k, const Monoid& x) {//k番目にxを代入
seg[k + sz] = x; //値をセット
}
void build() { //値をセットした後準備
for (int k = sz - 1; k > 0; k--) {
seg[k] = f(seg[2 * k + 0], seg[2 * k + 1]);
}
}
void update(int k, const Monoid& x) {//k番目にxを更新
k += sz;
seg[k] = x;//セット
while (k >>= 1) {//更新
seg[k] = f(seg[2 * k + 0], seg[2 * k + 1]);
}
}
Monoid query(int a, int b) { //[a,b)の最小値
Monoid L = M1, R = M1; //INFをセット
for (a += sz, b += sz; a < b; a >>= 1, b >>= 1) {
if (a & 1) L = f(L, seg[a++]);//上に遡る
if (b & 1) R = f(seg[--b], R);
}
return f(L, R);
}
Monoid operator[](const int& k) const {
return seg[k + sz];//値を返す
}
};