sotanishy's code snippets for competitive programming
#include "data-structure/segtree/dynamic_segment_tree.hpp"
動的セグメント木は,モノイド $(T, \cdot, e)$ の列に対する一点更新と区間取得を提供するデータ構造である.必要なノードだけを動的に構築することで, $n$ が非常に大きい場合でも効率的に値を管理することができる.
空間計算量: $O(m\log n)$.$m$ は追加した要素の数
DynamicSegmentTree(long long n)
n
で要素がすべて単位元 $e$ の動的セグメント木を構築するT operator[](long long k)
void update(long long k, T x)
T fold(long long l, long long r)
#pragma once
#include <bit>
#include <memory>
template <typename M>
class DynamicSegmentTree {
using T = M::T;
public:
DynamicSegmentTree() = default;
explicit DynamicSegmentTree(long long n)
: root(std::make_unique<Node>()),
size(std::bit_ceil((unsigned long long)n)) {}
T operator[](long long k) const { return fold(k, k + 1); }
void update(long long k, const T& x) const { update(k, x, root, 0, size); }
T fold(long long l, long long r) const { return fold(l, r, root, 0, size); }
private:
struct Node;
using node_ptr = std::unique_ptr<Node>;
struct Node {
T val;
node_ptr left, right;
Node() : val(M::id()), left(nullptr), right(nullptr) {}
};
const node_ptr root;
long long size;
void update(long long k, const T& x, const node_ptr& n, long long l,
long long r) const {
if (r - l == 1) {
n->val = x;
return;
}
long long m = std::midpoint(l, r);
if (k < m) {
if (!n->left) n->left = std::make_unique<Node>();
update(k, x, n->left, l, m);
n->val = M::op(n->left->val, n->right ? n->right->val : M::id());
} else {
if (!n->right) n->right = std::make_unique<Node>();
update(k, x, n->right, m, r);
n->val = M::op(n->left ? n->left->val : M::id(), n->right->val);
}
}
T fold(long long a, long long b, const node_ptr& n, long long l,
long long r) const {
if (r <= a || b <= l) return M::id();
if (a <= l && r <= b) return n->val;
long long m = std::midpoint(l, r);
T vl = n->left ? fold(a, b, n->left, l, m) : M::id();
T vr = n->right ? fold(a, b, n->right, m, r) : M::id();
return M::op(vl, vr);
}
};
#line 2 "data-structure/segtree/dynamic_segment_tree.hpp"
#include <bit>
#include <memory>
template <typename M>
class DynamicSegmentTree {
using T = M::T;
public:
DynamicSegmentTree() = default;
explicit DynamicSegmentTree(long long n)
: root(std::make_unique<Node>()),
size(std::bit_ceil((unsigned long long)n)) {}
T operator[](long long k) const { return fold(k, k + 1); }
void update(long long k, const T& x) const { update(k, x, root, 0, size); }
T fold(long long l, long long r) const { return fold(l, r, root, 0, size); }
private:
struct Node;
using node_ptr = std::unique_ptr<Node>;
struct Node {
T val;
node_ptr left, right;
Node() : val(M::id()), left(nullptr), right(nullptr) {}
};
const node_ptr root;
long long size;
void update(long long k, const T& x, const node_ptr& n, long long l,
long long r) const {
if (r - l == 1) {
n->val = x;
return;
}
long long m = std::midpoint(l, r);
if (k < m) {
if (!n->left) n->left = std::make_unique<Node>();
update(k, x, n->left, l, m);
n->val = M::op(n->left->val, n->right ? n->right->val : M::id());
} else {
if (!n->right) n->right = std::make_unique<Node>();
update(k, x, n->right, m, r);
n->val = M::op(n->left ? n->left->val : M::id(), n->right->val);
}
}
T fold(long long a, long long b, const node_ptr& n, long long l,
long long r) const {
if (r <= a || b <= l) return M::id();
if (a <= l && r <= b) return n->val;
long long m = std::midpoint(l, r);
T vl = n->left ? fold(a, b, n->left, l, m) : M::id();
T vr = n->right ? fold(a, b, n->right, m, r) : M::id();
return M::op(vl, vr);
}
};