This documentation is automatically generated by online-judge-tools/verification-helper
#include "ds/segtree/dynamic_segtree_sparse.hpp"
#pragma once
// 常にほとんどの要素が unit であることが保証されるような動的セグ木
// したがって、default_prod の類は持たせられず、acted monoid も一般には扱えない
// 追加 N 回のときノード数 N 以下が保証される
template <typename Monoid, bool PERSISTENT>
struct Dynamic_SegTree_Sparse {
using MX = Monoid;
using X = typename MX::value_type;
struct Node {
ll idx;
Node *l, *r;
X prod, x;
};
const int NODES;
const ll L0, R0;
Node *pool;
int pid;
using np = Node *;
vc<np> FREE;
Dynamic_SegTree_Sparse(int NODES, ll L0, ll R0) : NODES(NODES), L0(L0), R0(R0), pid(0) { pool = new Node[NODES]; }
~Dynamic_SegTree_Sparse() { delete[] pool; }
// 木 dp のマージのときなどに使用すると MLE 回避できることがある
// https://codeforces.com/problemset/problem/671/D
void free_subtree(np c) {
auto dfs = [&](auto &dfs, np c) -> void {
if (c->l) dfs(dfs, c->l);
if (c->r) dfs(dfs, c->r);
FREE.eb(c);
};
dfs(dfs, c);
}
np new_root() { return nullptr; }
np new_node(ll idx, const X x) {
if (!FREE.empty()) {
np c = POP(FREE);
c->idx = idx, c->l = c->r = nullptr;
c->prod = c->x = x;
return c;
}
assert(pid < NODES);
pool[pid].idx = idx;
pool[pid].l = pool[pid].r = nullptr;
pool[pid].x = pool[pid].prod = x;
return &(pool[pid++]);
}
X prod(np root, ll l, ll r) {
assert(L0 <= l && l <= r && r <= R0);
if (l == r) return MX::unit();
X x = MX::unit();
prod_rec(root, L0, R0, l, r, x);
return x;
}
X prod_all(np root) { return prod(root, L0, R0); }
np set(np root, ll i, const X &x) {
assert(L0 <= i && i < R0);
return set_rec(root, L0, R0, i, x);
}
np multiply(np root, ll i, const X &x) {
assert(L0 <= i && i < R0);
return multiply_rec(root, L0, R0, i, x);
}
template <typename F>
ll max_right(np root, F check, ll L) {
assert(L0 <= L && L <= R0 && check(MX::unit()));
X x = MX::unit();
return max_right_rec(root, check, L0, R0, L, x);
}
template <typename F>
ll min_left(np root, F check, ll R) {
assert(L0 <= R && R <= R0 && check(MX::unit()));
X x = MX::unit();
return min_left_rec(root, check, L0, R0, R, x);
}
void reset() {
pid = 0;
FREE.clear();
}
vc<pair<ll, X>> get_all(np root) {
vc<pair<ll, X>> res;
auto dfs = [&](auto &dfs, np c) -> void {
if (!c) return;
dfs(dfs, c->l);
res.eb(c->idx, c->x);
dfs(dfs, c->r);
};
dfs(dfs, root);
return res;
}
X get(np root, ll idx) {
auto dfs = [&](auto &dfs, np c) -> X {
if (!c) return Monoid::unit();
if (idx == c->idx) return c->x;
if (idx < (c->idx)) return dfs(dfs, c->l);
return dfs(dfs, c->r);
};
return dfs(dfs, root);
}
private:
void update(np c) {
c->prod = c->x;
if (c->l) c->prod = MX::op(c->l->prod, c->prod);
if (c->r) c->prod = MX::op(c->prod, c->r->prod);
}
np copy_node(np c) {
if (!c || !PERSISTENT) return c;
assert(pid < NODES);
pool[pid].idx = c->idx;
pool[pid].l = c->l;
pool[pid].r = c->r;
pool[pid].x = c->x;
pool[pid].prod = c->prod;
return &(pool[pid++]);
}
np set_rec(np c, ll l, ll r, ll i, X x) {
if (!c) {
c = new_node(i, x);
return c;
}
c = copy_node(c);
if (c->idx == i) {
c->x = x;
update(c);
return c;
}
ll m = (l + r) / 2;
if (i < m) {
if (c->idx < i) swap(c->idx, i), swap(c->x, x);
c->l = set_rec(c->l, l, m, i, x);
}
if (m <= i) {
if (i < c->idx) swap(c->idx, i), swap(c->x, x);
c->r = set_rec(c->r, m, r, i, x);
}
update(c);
return c;
}
np multiply_rec(np c, ll l, ll r, ll i, X x) {
if (!c) {
c = new_node(i, x);
return c;
}
c = copy_node(c);
if (c->idx == i) {
c->x = MX::op(c->x, x);
update(c);
return c;
}
ll m = (l + r) / 2;
if (i < m) {
if (c->idx < i) swap(c->idx, i), swap(c->x, x);
c->l = multiply_rec(c->l, l, m, i, x);
}
if (m <= i) {
if (i < c->idx) swap(c->idx, i), swap(c->x, x);
c->r = multiply_rec(c->r, m, r, i, x);
}
update(c);
return c;
}
void prod_rec(np c, ll l, ll r, ll ql, ll qr, X &x) {
chmax(ql, l);
chmin(qr, r);
if (ql >= qr || !c) return;
if (l == ql && r == qr) {
x = MX::op(x, c->prod);
return;
}
ll m = (l + r) / 2;
prod_rec(c->l, l, m, ql, qr, x);
if (ql <= (c->idx) && (c->idx) < qr) x = MX::op(x, c->x);
prod_rec(c->r, m, r, ql, qr, x);
}
template <typename F>
ll max_right_rec(np c, const F &check, ll l, ll r, ll ql, X &x) {
if (!c || r <= ql) return R0;
if (check(MX::op(x, c->prod))) {
x = MX::op(x, c->prod);
return R0;
}
ll m = (l + r) / 2;
ll k = max_right_rec(c->l, check, l, m, ql, x);
if (k != R0) return k;
if (ql <= (c->idx)) {
x = MX::op(x, c->x);
if (!check(x)) return c->idx;
}
return max_right_rec(c->r, check, m, r, ql, x);
}
template <typename F>
ll min_left_rec(np c, const F &check, ll l, ll r, ll qr, X &x) {
if (!c || qr <= l) return L0;
if (check(MX::op(c->prod, x))) {
x = MX::op(c->prod, x);
return L0;
}
ll m = (l + r) / 2;
ll k = min_left_rec(c->r, check, m, r, qr, x);
if (k != L0) return k;
if (c->idx < qr) {
x = MX::op(c->x, x);
if (!check(x)) return c->idx + 1;
}
return min_left_rec(c->l, check, l, m, qr, x);
}
};
#line 2 "ds/segtree/dynamic_segtree_sparse.hpp"
// 常にほとんどの要素が unit であることが保証されるような動的セグ木
// したがって、default_prod の類は持たせられず、acted monoid も一般には扱えない
// 追加 N 回のときノード数 N 以下が保証される
template <typename Monoid, bool PERSISTENT>
struct Dynamic_SegTree_Sparse {
using MX = Monoid;
using X = typename MX::value_type;
struct Node {
ll idx;
Node *l, *r;
X prod, x;
};
const int NODES;
const ll L0, R0;
Node *pool;
int pid;
using np = Node *;
vc<np> FREE;
Dynamic_SegTree_Sparse(int NODES, ll L0, ll R0) : NODES(NODES), L0(L0), R0(R0), pid(0) { pool = new Node[NODES]; }
~Dynamic_SegTree_Sparse() { delete[] pool; }
// 木 dp のマージのときなどに使用すると MLE 回避できることがある
// https://codeforces.com/problemset/problem/671/D
void free_subtree(np c) {
auto dfs = [&](auto &dfs, np c) -> void {
if (c->l) dfs(dfs, c->l);
if (c->r) dfs(dfs, c->r);
FREE.eb(c);
};
dfs(dfs, c);
}
np new_root() { return nullptr; }
np new_node(ll idx, const X x) {
if (!FREE.empty()) {
np c = POP(FREE);
c->idx = idx, c->l = c->r = nullptr;
c->prod = c->x = x;
return c;
}
assert(pid < NODES);
pool[pid].idx = idx;
pool[pid].l = pool[pid].r = nullptr;
pool[pid].x = pool[pid].prod = x;
return &(pool[pid++]);
}
X prod(np root, ll l, ll r) {
assert(L0 <= l && l <= r && r <= R0);
if (l == r) return MX::unit();
X x = MX::unit();
prod_rec(root, L0, R0, l, r, x);
return x;
}
X prod_all(np root) { return prod(root, L0, R0); }
np set(np root, ll i, const X &x) {
assert(L0 <= i && i < R0);
return set_rec(root, L0, R0, i, x);
}
np multiply(np root, ll i, const X &x) {
assert(L0 <= i && i < R0);
return multiply_rec(root, L0, R0, i, x);
}
template <typename F>
ll max_right(np root, F check, ll L) {
assert(L0 <= L && L <= R0 && check(MX::unit()));
X x = MX::unit();
return max_right_rec(root, check, L0, R0, L, x);
}
template <typename F>
ll min_left(np root, F check, ll R) {
assert(L0 <= R && R <= R0 && check(MX::unit()));
X x = MX::unit();
return min_left_rec(root, check, L0, R0, R, x);
}
void reset() {
pid = 0;
FREE.clear();
}
vc<pair<ll, X>> get_all(np root) {
vc<pair<ll, X>> res;
auto dfs = [&](auto &dfs, np c) -> void {
if (!c) return;
dfs(dfs, c->l);
res.eb(c->idx, c->x);
dfs(dfs, c->r);
};
dfs(dfs, root);
return res;
}
X get(np root, ll idx) {
auto dfs = [&](auto &dfs, np c) -> X {
if (!c) return Monoid::unit();
if (idx == c->idx) return c->x;
if (idx < (c->idx)) return dfs(dfs, c->l);
return dfs(dfs, c->r);
};
return dfs(dfs, root);
}
private:
void update(np c) {
c->prod = c->x;
if (c->l) c->prod = MX::op(c->l->prod, c->prod);
if (c->r) c->prod = MX::op(c->prod, c->r->prod);
}
np copy_node(np c) {
if (!c || !PERSISTENT) return c;
assert(pid < NODES);
pool[pid].idx = c->idx;
pool[pid].l = c->l;
pool[pid].r = c->r;
pool[pid].x = c->x;
pool[pid].prod = c->prod;
return &(pool[pid++]);
}
np set_rec(np c, ll l, ll r, ll i, X x) {
if (!c) {
c = new_node(i, x);
return c;
}
c = copy_node(c);
if (c->idx == i) {
c->x = x;
update(c);
return c;
}
ll m = (l + r) / 2;
if (i < m) {
if (c->idx < i) swap(c->idx, i), swap(c->x, x);
c->l = set_rec(c->l, l, m, i, x);
}
if (m <= i) {
if (i < c->idx) swap(c->idx, i), swap(c->x, x);
c->r = set_rec(c->r, m, r, i, x);
}
update(c);
return c;
}
np multiply_rec(np c, ll l, ll r, ll i, X x) {
if (!c) {
c = new_node(i, x);
return c;
}
c = copy_node(c);
if (c->idx == i) {
c->x = MX::op(c->x, x);
update(c);
return c;
}
ll m = (l + r) / 2;
if (i < m) {
if (c->idx < i) swap(c->idx, i), swap(c->x, x);
c->l = multiply_rec(c->l, l, m, i, x);
}
if (m <= i) {
if (i < c->idx) swap(c->idx, i), swap(c->x, x);
c->r = multiply_rec(c->r, m, r, i, x);
}
update(c);
return c;
}
void prod_rec(np c, ll l, ll r, ll ql, ll qr, X &x) {
chmax(ql, l);
chmin(qr, r);
if (ql >= qr || !c) return;
if (l == ql && r == qr) {
x = MX::op(x, c->prod);
return;
}
ll m = (l + r) / 2;
prod_rec(c->l, l, m, ql, qr, x);
if (ql <= (c->idx) && (c->idx) < qr) x = MX::op(x, c->x);
prod_rec(c->r, m, r, ql, qr, x);
}
template <typename F>
ll max_right_rec(np c, const F &check, ll l, ll r, ll ql, X &x) {
if (!c || r <= ql) return R0;
if (check(MX::op(x, c->prod))) {
x = MX::op(x, c->prod);
return R0;
}
ll m = (l + r) / 2;
ll k = max_right_rec(c->l, check, l, m, ql, x);
if (k != R0) return k;
if (ql <= (c->idx)) {
x = MX::op(x, c->x);
if (!check(x)) return c->idx;
}
return max_right_rec(c->r, check, m, r, ql, x);
}
template <typename F>
ll min_left_rec(np c, const F &check, ll l, ll r, ll qr, X &x) {
if (!c || qr <= l) return L0;
if (check(MX::op(c->prod, x))) {
x = MX::op(c->prod, x);
return L0;
}
ll m = (l + r) / 2;
ll k = min_left_rec(c->r, check, m, r, qr, x);
if (k != L0) return k;
if (c->idx < qr) {
x = MX::op(c->x, x);
if (!check(x)) return c->idx + 1;
}
return min_left_rec(c->l, check, l, m, qr, x);
}
};