This documentation is automatically generated by online-judge-tools/verification-helper
#include "segment_tree/segment_tree_recursion.hpp"Persistent Segment Tree の理解のために Segment Tree を再帰 + ポインタ木で書き直したものです。
Segment Tree と比較すると以下のような欠点があります。
したがって、基本的には実際のコンテストで使うメリットはありません。
(1) SegmentTreeRecursion<M> seg(int n)
(2) SegmentTreeRecursion<M> seg(std::vector<S> v)
(1)
長さ $n$ の数列 $a$ を作ります。初期値は全部 $e$ です。
(2)
長さ $ n = \left| v \right| $ の数列 $a$ を作ります。 $v$ の内容が初期値となります。
void seg.set(int p, S x)
$a_p$ に $x$ を代入します。
void seg.add(int p, S x)
$a_p$ に $a_p \cdot x$ を代入します。
(1) S seg.get(int p)
(2) S seg[int p]
$a_p$ を返します。
S seg.prod(int l, int r)
$a_l \cdot … \cdot a_{r - 1}$ を、モノイドの性質を満たしていると仮定して計算します。 $l = r$ のときは $e$ を返します。
S seg.all_prod()
$a_0 \cdot …\cdot a_{n - 1}$ を計算します。 $n = 0$ のときは $e$ を返します。
std::vector<S> seg.make_vector()
現在の数列 $a$ を返します。
#pragma once
#include <cassert>
#include <vector>
// Segment Tree (再帰 + ポインタ木)
// 2N は N = 500000 のとき 1000000 くらい
template <class MS, int MAX_NODES = 2'000'000> struct SegmentTreeRecursion {
public:
using S = typename MS::value_type;
struct Node {
S d;
Node *l, *r;
Node() = default;
Node(S v, Node* l = nullptr, Node* r = nullptr) : d(v), l(l), r(r) {}
};
SegmentTreeRecursion() = default;
explicit SegmentTreeRecursion(int n)
: SegmentTreeRecursion(std::vector<S>(n, MS::identity())) {}
explicit SegmentTreeRecursion(const std::vector<S>& v)
: n((int)(v.size())) {
root = build(v, 0, n);
}
void set(int p, const S& x) {
assert(0 <= p and p < n);
set(p, x, 0, n, root);
}
void add(int p, const S& x) {
assert(0 <= p and p < n);
add(p, x, 0, n, root);
}
S operator[](int p) const {
assert(0 <= p and p < n);
return prod(p, p + 1);
}
S get(int p) const {
assert(0 <= p and p < n);
return prod(p, p + 1);
}
S prod(int l, int r) const {
assert(0 <= l and l <= r and r <= n);
return prod(l, r, 0, n, root);
}
S all_prod() const { return root->d; }
std::vector<S> make_vector() const {
std::vector<S> vec(n);
for (int i = 0; i < n; i++) vec[i] = get(i);
return vec;
}
private:
int n;
Node* root;
static inline Node pool[MAX_NODES];
static inline int pool_idx = 0;
Node* new_node(S v, Node* l = nullptr, Node* r = nullptr) {
return &(pool[pool_idx++] = Node(v, l, r));
}
Node* merge(Node* l, Node* r, Node* np = nullptr) {
if (np == nullptr) {
np = new_node(MS::operation(l->d, r->d), l, r);
} else {
np->d = MS::operation(l->d, r->d);
}
return np;
}
Node* build(const std::vector<S>& v, int l, int r) {
if (l + 1 == r) {
return new_node(v[l]);
}
int m = (l + r) / 2;
return merge(build(v, l, m), build(v, m, r));
}
Node* set(int p, const S& x, int l, int r, Node* np) {
if (l + 1 == r) {
np->d = x;
return np;
}
int m = (l + r) / 2;
if (l <= p and p < m) {
return merge(set(p, x, l, m, np->l), np->r, np);
} else {
return merge(np->l, set(p, x, m, r, np->r), np);
}
}
Node* add(int p, const S& x, int l, int r, Node* np) {
if (l + 1 == r) {
np->d = MS::operation(np->d, x);
return np;
}
int m = (l + r) / 2;
if (l <= p and p < m) {
return merge(add(p, x, l, m, np->l), np->r, np);
} else {
return merge(np->l, add(p, x, m, r, np->r), np);
}
}
S prod(int ql, int qr, int l, int r, Node* np) const {
// [ql, qr) と [l, r) が交差しない
if (qr <= l or r <= ql) return MS::identity();
// [ql, qr) が [l, r) を完全に含んでいる
if (ql <= l and r <= qr) return np->d;
int m = (l + r) / 2;
return MS::operation(prod(ql, qr, l, m, np->l),
prod(ql, qr, m, r, np->r));
}
};#line 2 "segment_tree/segment_tree_recursion.hpp"
#include <cassert>
#include <vector>
// Segment Tree (再帰 + ポインタ木)
// 2N は N = 500000 のとき 1000000 くらい
template <class MS, int MAX_NODES = 2'000'000> struct SegmentTreeRecursion {
public:
using S = typename MS::value_type;
struct Node {
S d;
Node *l, *r;
Node() = default;
Node(S v, Node* l = nullptr, Node* r = nullptr) : d(v), l(l), r(r) {}
};
SegmentTreeRecursion() = default;
explicit SegmentTreeRecursion(int n)
: SegmentTreeRecursion(std::vector<S>(n, MS::identity())) {}
explicit SegmentTreeRecursion(const std::vector<S>& v)
: n((int)(v.size())) {
root = build(v, 0, n);
}
void set(int p, const S& x) {
assert(0 <= p and p < n);
set(p, x, 0, n, root);
}
void add(int p, const S& x) {
assert(0 <= p and p < n);
add(p, x, 0, n, root);
}
S operator[](int p) const {
assert(0 <= p and p < n);
return prod(p, p + 1);
}
S get(int p) const {
assert(0 <= p and p < n);
return prod(p, p + 1);
}
S prod(int l, int r) const {
assert(0 <= l and l <= r and r <= n);
return prod(l, r, 0, n, root);
}
S all_prod() const { return root->d; }
std::vector<S> make_vector() const {
std::vector<S> vec(n);
for (int i = 0; i < n; i++) vec[i] = get(i);
return vec;
}
private:
int n;
Node* root;
static inline Node pool[MAX_NODES];
static inline int pool_idx = 0;
Node* new_node(S v, Node* l = nullptr, Node* r = nullptr) {
return &(pool[pool_idx++] = Node(v, l, r));
}
Node* merge(Node* l, Node* r, Node* np = nullptr) {
if (np == nullptr) {
np = new_node(MS::operation(l->d, r->d), l, r);
} else {
np->d = MS::operation(l->d, r->d);
}
return np;
}
Node* build(const std::vector<S>& v, int l, int r) {
if (l + 1 == r) {
return new_node(v[l]);
}
int m = (l + r) / 2;
return merge(build(v, l, m), build(v, m, r));
}
Node* set(int p, const S& x, int l, int r, Node* np) {
if (l + 1 == r) {
np->d = x;
return np;
}
int m = (l + r) / 2;
if (l <= p and p < m) {
return merge(set(p, x, l, m, np->l), np->r, np);
} else {
return merge(np->l, set(p, x, m, r, np->r), np);
}
}
Node* add(int p, const S& x, int l, int r, Node* np) {
if (l + 1 == r) {
np->d = MS::operation(np->d, x);
return np;
}
int m = (l + r) / 2;
if (l <= p and p < m) {
return merge(add(p, x, l, m, np->l), np->r, np);
} else {
return merge(np->l, add(p, x, m, r, np->r), np);
}
}
S prod(int ql, int qr, int l, int r, Node* np) const {
// [ql, qr) と [l, r) が交差しない
if (qr <= l or r <= ql) return MS::identity();
// [ql, qr) が [l, r) を完全に含んでいる
if (ql <= l and r <= qr) return np->d;
int m = (l + r) / 2;
return MS::operation(prod(ql, qr, l, m, np->l),
prod(ql, qr, m, r, np->r));
}
};