#ifndef M1UNE_DS_DETAIL_PERSISTENT_BINARY_NODE_POOL_HPP
#define M1UNE_DS_DETAIL_PERSISTENT_BINARY_NODE_POOL_HPP 1
#include<cassert>
#include<cstddef>
#include<deque>
#include<limits>
#include<optional>
#include<utility>
#include<vector>namespacem1une{namespaceds{namespacedetail{// Node must have integer `l` and `r` members. New nodes initially have no// owner; discard_unreferenced() removes temporary path-copy nodes after the// result roots have been retained.template<classNode,intnull_node=-1>structPersistentBinaryNodePool{private:std::deque<std::optional<Node>>_nodes;std::vector<int>_references;std::vector<int>_next_free;std::vector<int>_unowned;int_first_free=-1;std::size_t_live_nodes=0;voidrelease_zero(intnode){assert(node!=null_node&&_nodes[node].has_value());intleft=(*_nodes[node]).l;intright=(*_nodes[node]).r;_nodes[node].reset();_next_free[node]=_first_free;_first_free=node;--_live_nodes;if(left!=null_node&&--_references[left]==0)release_zero(left);if(right!=null_node&&--_references[right]==0)release_zero(right);}public:PersistentBinaryNodePool(){ifconstexpr(null_node==0){_nodes.emplace_back();_references.push_back(0);_next_free.push_back(-1);}}Node&operator[](intnode){assert(node!=null_node&&_nodes[node].has_value());return*_nodes[node];}constNode&operator[](intnode)const{assert(node!=null_node&&_nodes[node].has_value());return*_nodes[node];}template<class...Args>intemplace(Args&&...args){intresult;if(_first_free==-1){assert(_nodes.size()<std::size_t(std::numeric_limits<int>::max()));result=int(_nodes.size());_nodes.emplace_back(std::in_place,std::forward<Args>(args)...);_references.push_back(0);_next_free.push_back(-1);}else{result=_first_free;_first_free=_next_free[result];_nodes[result].emplace(std::forward<Args>(args)...);_references[result]=0;}retain((*_nodes[result]).l);retain((*_nodes[result]).r);_unowned.push_back(result);++_live_nodes;returnresult;}voidretain(intnode){if(node!=null_node){assert(_nodes[node].has_value());++_references[node];}}voidrelease(intnode){if(node==null_node)return;assert(_nodes[node].has_value()&&_references[node]>0);if(--_references[node]==0)release_zero(node);}boolunique(intnode)const{returnnode==null_node||_references[node]==1;}intclone(intnode){assert(node!=null_node&&_nodes[node].has_value());returnemplace(*_nodes[node]);}// Returns node itself when it has one owner, otherwise an unowned clone.// A returned clone becomes owned when a root or parent edge retains it.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);}voiddiscard_unreferenced(){while(!_unowned.empty()){intnode=_unowned.back();_unowned.pop_back();if(_nodes[node].has_value()&&_references[node]==0)release_zero(node);}}voidreserve(std::size_t){}intnext_index()const{return_first_free==-1?int(_nodes.size()):_first_free;}std::size_tsize()const{return_live_nodes;}};}// namespace detail}// namespace ds}// namespace m1une#endif // M1UNE_DS_DETAIL_PERSISTENT_BINARY_NODE_POOL_HPP
#line 1 "ds/detail/persistent_binary_node_pool.hpp"
#include<cassert>
#include<cstddef>
#include<deque>
#include<limits>
#include<optional>
#include<utility>
#include<vector>namespacem1une{namespaceds{namespacedetail{// Node must have integer `l` and `r` members. New nodes initially have no// owner; discard_unreferenced() removes temporary path-copy nodes after the// result roots have been retained.template<classNode,intnull_node=-1>structPersistentBinaryNodePool{private:std::deque<std::optional<Node>>_nodes;std::vector<int>_references;std::vector<int>_next_free;std::vector<int>_unowned;int_first_free=-1;std::size_t_live_nodes=0;voidrelease_zero(intnode){assert(node!=null_node&&_nodes[node].has_value());intleft=(*_nodes[node]).l;intright=(*_nodes[node]).r;_nodes[node].reset();_next_free[node]=_first_free;_first_free=node;--_live_nodes;if(left!=null_node&&--_references[left]==0)release_zero(left);if(right!=null_node&&--_references[right]==0)release_zero(right);}public:PersistentBinaryNodePool(){ifconstexpr(null_node==0){_nodes.emplace_back();_references.push_back(0);_next_free.push_back(-1);}}Node&operator[](intnode){assert(node!=null_node&&_nodes[node].has_value());return*_nodes[node];}constNode&operator[](intnode)const{assert(node!=null_node&&_nodes[node].has_value());return*_nodes[node];}template<class...Args>intemplace(Args&&...args){intresult;if(_first_free==-1){assert(_nodes.size()<std::size_t(std::numeric_limits<int>::max()));result=int(_nodes.size());_nodes.emplace_back(std::in_place,std::forward<Args>(args)...);_references.push_back(0);_next_free.push_back(-1);}else{result=_first_free;_first_free=_next_free[result];_nodes[result].emplace(std::forward<Args>(args)...);_references[result]=0;}retain((*_nodes[result]).l);retain((*_nodes[result]).r);_unowned.push_back(result);++_live_nodes;returnresult;}voidretain(intnode){if(node!=null_node){assert(_nodes[node].has_value());++_references[node];}}voidrelease(intnode){if(node==null_node)return;assert(_nodes[node].has_value()&&_references[node]>0);if(--_references[node]==0)release_zero(node);}boolunique(intnode)const{returnnode==null_node||_references[node]==1;}intclone(intnode){assert(node!=null_node&&_nodes[node].has_value());returnemplace(*_nodes[node]);}// Returns node itself when it has one owner, otherwise an unowned clone.// A returned clone becomes owned when a root or parent edge retains it.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);}voiddiscard_unreferenced(){while(!_unowned.empty()){intnode=_unowned.back();_unowned.pop_back();if(_nodes[node].has_value()&&_references[node]==0)release_zero(node);}}voidreserve(std::size_t){}intnext_index()const{return_first_free==-1?int(_nodes.size()):_first_free;}std::size_tsize()const{return_live_nodes;}};}// namespace detail}// namespace ds}// namespace m1une