This documentation is automatically generated by competitive-verifier/competitive-verifier
#include "commutative_dual_segment_tree.hpp"
作用素の合成が可換な場合の双対セグ木。実装がより少ない。
1. CommutativeDualSegmentTree<F, composition, id>(int n)
2. CommutativeDualSegmentTree<F, composition, id>(vector<F> f)
F
F composition(F f, F g)
F id()
を受け取り、
n
、初期値 id()
で構築。f
で構築。F get(int p)
p
番目の作用素を取得。
void apply(int l, int r, F f)
$k\in[l, r)$ に対して、$k$ 番目の作用素に f
を合成。
template <class F, auto composition, auto id>
class CommutativeDualSegmentTree {
static_assert(is_convertible_v<decltype(composition), function<F(F, F)>>, "composition must work as F(F, F)");
static_assert(is_convertible_v<decltype(id), function<F()>>, "id must work as F()");
public:
CommutativeDualSegmentTree() : CommutativeDualSegmentTree(0) {}
explicit CommutativeDualSegmentTree(int n) : CommutativeDualSegmentTree(vector<F>(n, id())) {}
explicit CommutativeDualSegmentTree(vector<F> f) : n(int(f.size())) {
h = ceil_log2(n);
siz = (1 << h);
act = vector<F>(2 * siz, id());
copy(f.begin(), f.end(), act.begin() + siz);
}
F get(int p) {
assert(0 <= p && p <= n);
F f = id();
p += siz;
for (int i = 0; i <= h; ++i) f = composition(act[p >> i], f);
return f;
}
void apply(int k, F f) { apply(k, k + 1, f); }
void apply(int l, int r, F f) {
assert(0 <= l && l <= r && r <= n);
if (l == r) return;
l += siz;
r += siz;
while (l < r) {
if (l & 1) apply_inner(l++, f);
if (r & 1) apply_inner(--r, f);
l >>= 1;
r >>= 1;
}
}
private:
int n, h, siz;
vector<F> act;
void apply_inner(int k, F f) { act[k] = composition(f, act[k]); }
int ceil_log2(int x) {
int res = 0;
while ((1 << res) < x) ++res;
return res;
}
};
#line 1 "commutative_dual_segment_tree.hpp"
template <class F, auto composition, auto id>
class CommutativeDualSegmentTree {
static_assert(is_convertible_v<decltype(composition), function<F(F, F)>>, "composition must work as F(F, F)");
static_assert(is_convertible_v<decltype(id), function<F()>>, "id must work as F()");
public:
CommutativeDualSegmentTree() : CommutativeDualSegmentTree(0) {}
explicit CommutativeDualSegmentTree(int n) : CommutativeDualSegmentTree(vector<F>(n, id())) {}
explicit CommutativeDualSegmentTree(vector<F> f) : n(int(f.size())) {
h = ceil_log2(n);
siz = (1 << h);
act = vector<F>(2 * siz, id());
copy(f.begin(), f.end(), act.begin() + siz);
}
F get(int p) {
assert(0 <= p && p <= n);
F f = id();
p += siz;
for (int i = 0; i <= h; ++i) f = composition(act[p >> i], f);
return f;
}
void apply(int k, F f) { apply(k, k + 1, f); }
void apply(int l, int r, F f) {
assert(0 <= l && l <= r && r <= n);
if (l == r) return;
l += siz;
r += siz;
while (l < r) {
if (l & 1) apply_inner(l++, f);
if (r & 1) apply_inner(--r, f);
l >>= 1;
r >>= 1;
}
}
private:
int n, h, siz;
vector<F> act;
void apply_inner(int k, F f) { act[k] = composition(f, act[k]); }
int ceil_log2(int x) {
int res = 0;
while ((1 << res) < x) ++res;
return res;
}
};