#ifndef M1UNE_PERSISTENT_NODE_POOL_HPP
#define M1UNE_PERSISTENT_NODE_POOL_HPP 1
#include<cassert>
#include<cstddef>
#include<limits>
#include<utility>
#include<vector>namespacem1une{namespaceds{namespacedetail{// Node must have integer `left`, `right`, and `references` members.template<classNode>structPersistentNodePool{std::vector<Node>nodes;intfirst_free=0;std::size_tlive_nodes=0;private:voidrelease_zero(intnode){intleft=nodes[node].left;intright=nodes[node].right;nodes[node]=Node();nodes[node].left=first_free;first_free=node;--live_nodes;if(left&&--nodes[left].references==0)release_zero(left);if(right&&--nodes[right].references==0)release_zero(right);}public:PersistentNodePool(){nodes.emplace_back();}voidreserve(std::size_tcapacity){nodes.reserve(capacity+1);}Node&operator[](intnode){returnnodes[node];}constNode&operator[](intnode)const{returnnodes[node];}voidretain(intnode){if(node)++nodes[node].references;}voidrelease(intnode){if(!node)return;assert(nodes[node].references>0);if(--nodes[node].references==0)release_zero(node);}template<class...Args>intemplace(Args&&...args){intresult;if(!first_free){assert(nodes.size()<std::size_t(std::numeric_limits<int>::max()));nodes.emplace_back(std::forward<Args>(args)...);result=int(nodes.size())-1;}else{result=first_free;first_free=nodes[result].left;nodes[result]=Node(std::forward<Args>(args)...);}Node&node=nodes[result];node.references=0;retain(node.left);retain(node.right);++live_nodes;returnresult;}intclone(intnode){assert(node);Nodecopy=nodes[node];returnemplace(std::move(copy));}boolunique(intnode)const{return!node||nodes[node].references==1;}// Returns node itself when it has one owner, otherwise an unowned clone.// The caller must attach a returned clone with replace() before it can be// released or exposed as a root.intclone_if_shared(intnode){if(unique(node))returnnode;returnclone(node);}voidreplace(int&edge,intnode){if(edge==node)return;retain(node);intold=edge;edge=node;release(old);}std::size_tsize()const{returnlive_nodes;}};}// namespace detail}// namespace ds}// namespace m1une#endif // M1UNE_PERSISTENT_NODE_POOL_HPP
#line 1 "ds/segtree/persistent_node_pool.hpp"
#include<cassert>
#include<cstddef>
#include<limits>
#include<utility>
#include<vector>namespacem1une{namespaceds{namespacedetail{// Node must have integer `left`, `right`, and `references` members.template<classNode>structPersistentNodePool{std::vector<Node>nodes;intfirst_free=0;std::size_tlive_nodes=0;private:voidrelease_zero(intnode){intleft=nodes[node].left;intright=nodes[node].right;nodes[node]=Node();nodes[node].left=first_free;first_free=node;--live_nodes;if(left&&--nodes[left].references==0)release_zero(left);if(right&&--nodes[right].references==0)release_zero(right);}public:PersistentNodePool(){nodes.emplace_back();}voidreserve(std::size_tcapacity){nodes.reserve(capacity+1);}Node&operator[](intnode){returnnodes[node];}constNode&operator[](intnode)const{returnnodes[node];}voidretain(intnode){if(node)++nodes[node].references;}voidrelease(intnode){if(!node)return;assert(nodes[node].references>0);if(--nodes[node].references==0)release_zero(node);}template<class...Args>intemplace(Args&&...args){intresult;if(!first_free){assert(nodes.size()<std::size_t(std::numeric_limits<int>::max()));nodes.emplace_back(std::forward<Args>(args)...);result=int(nodes.size())-1;}else{result=first_free;first_free=nodes[result].left;nodes[result]=Node(std::forward<Args>(args)...);}Node&node=nodes[result];node.references=0;retain(node.left);retain(node.right);++live_nodes;returnresult;}intclone(intnode){assert(node);Nodecopy=nodes[node];returnemplace(std::move(copy));}boolunique(intnode)const{return!node||nodes[node].references==1;}// Returns node itself when it has one owner, otherwise an unowned clone.// The caller must attach a returned clone with replace() before it can be// released or exposed as a root.intclone_if_shared(intnode){if(unique(node))returnnode;returnclone(node);}voidreplace(int&edge,intnode){if(edge==node)return;retain(node);intold=edge;edge=node;release(old);}std::size_tsize()const{returnlive_nodes;}};}// namespace detail}// namespace ds}// namespace m1une