永続セグメント木
(segment-tree/persistent-segment-tree.hpp)
- View this file on GitHub
- Last update: 2020-12-05 07:59:51+09:00
- Include:
#include "segment-tree/persistent-segment-tree.hpp"
永続セグメント木(Persistent Segment Tree)
永続セグメント木とはセグメント木を完全永続化したデータ構造である。完全永続化とは、更新をする時に更新前のデータを残したり、最新でないデータを元として更新したりできるようにすることである。
複雑な割にほとんど使わないので忘れないうちに使い方を簡単にメモ。
使い方
-
PersistentSegmentTree(v, f, ID)
:= 要素を$v$、マージ関数を$f$とする木を作成する。(fはモノイドである必要がある。) -
update,add,query
は通常のセグ木と同様だが、使用方法に応じてそれぞれ3種類の関数が存在する。-
update(Node *n, k, x)
:= nを根とする木を更新元とする。 -
update(int t, k, x)
:= t回目の更新の後の木を更新元とする。 -
update(k, x)
:= 最新の木を更新元とする。
-
-
new_tree()
:= 空の木を返す
Required by
Verified with
Code
#pragma once
template <typename T, typename F, int NODES = 20000000>
struct PersistentSegmentTree {
using ll = long long;
struct Node {
T data;
Node *l, *r;
Node() {}
Node(const T &_data) : data(_data), l(nullptr), r(nullptr) {}
};
Node *pool;
int pid;
ll N;
const F f;
const T ID;
Node *nil;
vector<Node *> roots;
PersistentSegmentTree(const vector<T> &v, const F &f_, const T &ID_)
: pid(0), f(f_), ID(ID_), nil(nullptr) {
pool = new Node[NODES];
nil = my_new(ID);
nil->l = nil->r = nil;
roots.reserve(262144);
roots.push_back(build(v));
}
PersistentSegmentTree(const ll &N_, const F &f_, const T &ID_)
: pid(0), N(N_), f(f_), ID(ID_), nil(nullptr) {
pool = new Node[NODES];
nil = my_new(ID);
nil->l = nil->r = nil;
roots.reserve(262144);
roots.push_back(nil);
}
Node *my_new(const T &data) {
pool[pid].data = data;
pool[pid].l = pool[pid].r = nil;
return &(pool[pid++]);
}
Node *merge(Node *l, Node *r) {
pool[pid].data = f(l->data, r->data);
pool[pid].l = l;
pool[pid].r = r;
return &(pool[pid++]);
}
Node *build(const vector<T> &v) {
N = (ll)v.size();
return build(0, (ll)v.size(), v);
}
Node *build(ll l, ll r, const vector<T> &v) {
if (l + 1 == r) return my_new(v[l]);
ll m = (l + r) >> 1;
return merge(build(l, m, v), build(m, r, v));
}
private:
Node *update_(ll a, const T &x, Node *n, ll l, ll r) {
if (l + 1 == r) return my_new(x);
ll m = (l + r) >> 1;
if (a < m) return merge(update_(a, x, n->l, l, m), n->r);
return merge(n->l, update_(a, x, n->r, m, r));
}
Node *add_(ll a, const T &x, Node *n, ll l, ll r) {
if (l + 1 == r) return my_new(f(x, n->data));
ll m = (l + r) >> 1;
if (a < m) return merge(add_(a, x, n->l, l, m), n->r);
return merge(n->l, add_(a, x, n->r, m, r));
}
T query_(ll a, ll b, Node *n, ll l, ll r) {
if (n == nil) return ID;
if (r <= a or b <= l) return ID;
if (a <= l and r <= b) return n->data;
ll m = (l + r) >> 1;
return f(query_(a, b, n->l, l, m), query_(a, b, n->r, m, r));
}
public:
Node *update(Node *n, ll k, const T &x) {
Node *root = update_(k, x, n, 0, N);
roots.push_back(root);
return root;
}
Node *update(int t, ll k, const T &x) {
Node *root = update_(k, x, roots[t], 0, N);
roots.push_back(root);
return root;
}
Node *update(ll k, const T &x) {
Node *root = update_(k, x, roots.back(), 0, N);
roots.push_back(root);
return root;
}
Node *add(Node *n, ll k, const T &x) {
Node *root = add_(k, x, n, 0, N);
roots.push_back(root);
return root;
}
Node *add(int t, ll k, const T &x) {
Node *root = add_(k, x, roots[t], 0, N);
roots.push_back(root);
return root;
}
Node *add(ll k, const T &x) {
Node *root = add_(k, x, roots.back(), 0, N);
roots.push_back(root);
return root;
}
T query(Node *n, ll a, ll b) { return query_(a, b, n, 0, N); }
T query(int t, ll a, ll b) { return query_(a, b, roots[t], 0, N); }
T query(ll a, ll b) { return query_(a, b, roots.back(), 0, N); }
Node *new_tree() { return nil; }
};
/**
* @brief 永続セグメント木
* @docs docs/segment-tree/persistent-segtree.md
*/
#line 2 "segment-tree/persistent-segment-tree.hpp"
template <typename T, typename F, int NODES = 20000000>
struct PersistentSegmentTree {
using ll = long long;
struct Node {
T data;
Node *l, *r;
Node() {}
Node(const T &_data) : data(_data), l(nullptr), r(nullptr) {}
};
Node *pool;
int pid;
ll N;
const F f;
const T ID;
Node *nil;
vector<Node *> roots;
PersistentSegmentTree(const vector<T> &v, const F &f_, const T &ID_)
: pid(0), f(f_), ID(ID_), nil(nullptr) {
pool = new Node[NODES];
nil = my_new(ID);
nil->l = nil->r = nil;
roots.reserve(262144);
roots.push_back(build(v));
}
PersistentSegmentTree(const ll &N_, const F &f_, const T &ID_)
: pid(0), N(N_), f(f_), ID(ID_), nil(nullptr) {
pool = new Node[NODES];
nil = my_new(ID);
nil->l = nil->r = nil;
roots.reserve(262144);
roots.push_back(nil);
}
Node *my_new(const T &data) {
pool[pid].data = data;
pool[pid].l = pool[pid].r = nil;
return &(pool[pid++]);
}
Node *merge(Node *l, Node *r) {
pool[pid].data = f(l->data, r->data);
pool[pid].l = l;
pool[pid].r = r;
return &(pool[pid++]);
}
Node *build(const vector<T> &v) {
N = (ll)v.size();
return build(0, (ll)v.size(), v);
}
Node *build(ll l, ll r, const vector<T> &v) {
if (l + 1 == r) return my_new(v[l]);
ll m = (l + r) >> 1;
return merge(build(l, m, v), build(m, r, v));
}
private:
Node *update_(ll a, const T &x, Node *n, ll l, ll r) {
if (l + 1 == r) return my_new(x);
ll m = (l + r) >> 1;
if (a < m) return merge(update_(a, x, n->l, l, m), n->r);
return merge(n->l, update_(a, x, n->r, m, r));
}
Node *add_(ll a, const T &x, Node *n, ll l, ll r) {
if (l + 1 == r) return my_new(f(x, n->data));
ll m = (l + r) >> 1;
if (a < m) return merge(add_(a, x, n->l, l, m), n->r);
return merge(n->l, add_(a, x, n->r, m, r));
}
T query_(ll a, ll b, Node *n, ll l, ll r) {
if (n == nil) return ID;
if (r <= a or b <= l) return ID;
if (a <= l and r <= b) return n->data;
ll m = (l + r) >> 1;
return f(query_(a, b, n->l, l, m), query_(a, b, n->r, m, r));
}
public:
Node *update(Node *n, ll k, const T &x) {
Node *root = update_(k, x, n, 0, N);
roots.push_back(root);
return root;
}
Node *update(int t, ll k, const T &x) {
Node *root = update_(k, x, roots[t], 0, N);
roots.push_back(root);
return root;
}
Node *update(ll k, const T &x) {
Node *root = update_(k, x, roots.back(), 0, N);
roots.push_back(root);
return root;
}
Node *add(Node *n, ll k, const T &x) {
Node *root = add_(k, x, n, 0, N);
roots.push_back(root);
return root;
}
Node *add(int t, ll k, const T &x) {
Node *root = add_(k, x, roots[t], 0, N);
roots.push_back(root);
return root;
}
Node *add(ll k, const T &x) {
Node *root = add_(k, x, roots.back(), 0, N);
roots.push_back(root);
return root;
}
T query(Node *n, ll a, ll b) { return query_(a, b, n, 0, N); }
T query(int t, ll a, ll b) { return query_(a, b, roots[t], 0, N); }
T query(ll a, ll b) { return query_(a, b, roots.back(), 0, N); }
Node *new_tree() { return nil; }
};
/**
* @brief 永続セグメント木
* @docs docs/segment-tree/persistent-segtree.md
*/