This documentation is automatically generated by online-judge-tools/verification-helper
#include "ds/dynamic_array.hpp"// Source: https://github.com/maspypy/library/blob/main/ds/dynamic_array.hpp
#include "ds/node_pool.hpp"
template <typename T, bool PERSISTENT>
struct Dynamic_Array {
static constexpr int LOG = 4;
static constexpr int MASK = (1 << LOG) - 1;
struct Node {
T x;
Node* ch[1 << LOG] = {};
};
Node_Pool<Node> pool;
using np = Node*;
const T x0;
Dynamic_Array(T default_value) : x0(default_value) {}
np new_root() {
np c = pool.create();
c->x = x0;
fill(c->ch, c->ch + (1 << LOG), nullptr);
return c;
}
np new_node(vc<T> dat) {
np root = new_root();
FOR(i, len(dat)) root = set(root, i, dat[i], false);
return root;
}
T get(np c, int idx) {
assert(0 <= idx);
if (!c) return x0;
if (idx == 0) return c->x;
return get(c->ch[idx & MASK], (idx - 1) >> LOG);
}
np set(np c, int idx, T x, bool make_copy = true) {
assert(0 <= idx);
c = (c ? clone(c, make_copy) : new_root());
if (idx == 0) {
c->x = x;
return c;
}
c->ch[idx & MASK] = set(c->ch[idx & MASK], (idx - 1) >> LOG, x);
return c;
}
private:
np clone(np c, bool make_copy) {
if (!make_copy || !PERSISTENT) return c;
return pool.clone(c);
}
};#line 1 "ds/dynamic_array.hpp"
// Source: https://github.com/maspypy/library/blob/main/ds/dynamic_array.hpp
#line 1 "ds/node_pool.hpp"
// Source: https://github.com/maspypy/library/blob/main/ds/node_pool.hpp
// マルチテストケースでも確保済み chunk を再利用する
template <class Node>
struct Node_Pool {
union Slot {
Node node;
Slot* next;
Slot() {}
~Slot() {}
};
using np = Node*;
static constexpr int CHUNK_SIZE = 1 << 12;
vc<unique_ptr<Slot[]>> chunks;
int chunk_id = 0;
int pos = 0;
Slot* free_head = nullptr;
~Node_Pool() {
auto& cache = chunk_cache();
for (auto& p : chunks) cache.eb(std::move(p));
}
template <class... Args>
np create(Args&&... args) {
Slot* s = new_slot();
return ::new (&s->node) Node(forward<Args>(args)...);
}
np clone(const np x) {
assert(x);
Slot* s = new_slot();
return ::new (&s->node) Node(*x);
}
void destroy(np x) {
if (!x) return;
x->~Node();
Slot* s = reinterpret_cast<Slot*>(x);
s->next = free_head;
free_head = s;
}
// 全 node を無効化する。
// 確保済み chunk は解放せず、次回以降に再利用する。
void reset() {
free_head = nullptr;
chunk_id = 0;
pos = 0;
}
int used() const { return chunk_id * CHUNK_SIZE + pos; }
private:
static vc<unique_ptr<Slot[]>>& chunk_cache() {
// static Node_Pool の destructor より先に破棄されないようにする。
static auto* cache = new vc<unique_ptr<Slot[]>>();
return *cache;
}
void alloc_chunk() {
auto& cache = chunk_cache();
if (cache.empty()) {
chunks.eb(make_unique<Slot[]>(CHUNK_SIZE));
} else {
chunks.eb(std::move(cache.back()));
cache.pop_back();
}
}
Slot* new_slot() {
if (free_head) {
Slot* s = free_head;
free_head = free_head->next;
return s;
}
if (chunk_id == len(chunks)) alloc_chunk();
Slot* s = &chunks[chunk_id][pos++];
if (pos == CHUNK_SIZE) {
++chunk_id;
pos = 0;
}
return s;
}
};
#line 3 "ds/dynamic_array.hpp"
template <typename T, bool PERSISTENT>
struct Dynamic_Array {
static constexpr int LOG = 4;
static constexpr int MASK = (1 << LOG) - 1;
struct Node {
T x;
Node* ch[1 << LOG] = {};
};
Node_Pool<Node> pool;
using np = Node*;
const T x0;
Dynamic_Array(T default_value) : x0(default_value) {}
np new_root() {
np c = pool.create();
c->x = x0;
fill(c->ch, c->ch + (1 << LOG), nullptr);
return c;
}
np new_node(vc<T> dat) {
np root = new_root();
FOR(i, len(dat)) root = set(root, i, dat[i], false);
return root;
}
T get(np c, int idx) {
assert(0 <= idx);
if (!c) return x0;
if (idx == 0) return c->x;
return get(c->ch[idx & MASK], (idx - 1) >> LOG);
}
np set(np c, int idx, T x, bool make_copy = true) {
assert(0 <= idx);
c = (c ? clone(c, make_copy) : new_root());
if (idx == 0) {
c->x = x;
return c;
}
c->ch[idx & MASK] = set(c->ch[idx & MASK], (idx - 1) >> LOG, x);
return c;
}
private:
np clone(np c, bool make_copy) {
if (!make_copy || !PERSISTENT) return c;
return pool.clone(c);
}
};