#ifndef M1UNE_DS_PERSISTENT_SEGTREE_BEATS_HPP
#define M1UNE_DS_PERSISTENT_SEGTREE_BEATS_HPP 1
#include<cassert>
#include<concepts>
#include<cstddef>
#include<memory>
#include<utility>
#include<vector>#include"../../beats_acted_monoid/concept.hpp"
#include"persistent_node_pool.hpp"namespacem1une{namespaceds{// A persistent Segment Tree Beats for fallible monoid actions.template<m1une::beats_acted_monoid::IsBeatsActedMonoidActedMonoid>structPersistentSegtreeBeats{usingvalue_type=typenameActedMonoid::value_type;usingoperator_type=typenameActedMonoid::operator_type;usingT=value_type;usingF=operator_type;private:structNode{Tval;Flazy;intleft;intright;intreferences;boolhas_lazy;Node():val(ActedMonoid::id()),lazy(ActedMonoid::op_id()),left(0),right(0),references(0),has_lazy(false){}explicitNode(Tvalue):val(std::move(value)),lazy(ActedMonoid::op_id()),left(0),right(0),references(0),has_lazy(false){}Node(Tvalue,intleft_child,intright_child):val(std::move(value)),lazy(ActedMonoid::op_id()),left(left_child),right(right_child),references(0),has_lazy(false){}};usingPool=detail::PersistentNodePool<Node>;int_n;int_root;std::shared_ptr<Pool>_pool;explicitPersistentSegtreeBeats(intn,introot,std::shared_ptr<Pool>pool):_n(n),_root(root),_pool(std::move(pool)){_pool->retain(_root);}intnew_node(constNode&node)const{return_pool->emplace(node);}intnew_node(Node&&node)const{return_pool->emplace(std::move(node));}intclone_node(intnode)const{return_pool->clone(node);}template<typenameU>staticTmake_value(constU&value,intindex){ifconstexpr(requires(Ux){ActedMonoid::make(x);}){returnActedMonoid::make(value);}elseifconstexpr(requires(Ux,inti){ActedMonoid::make(x,i);}){returnActedMonoid::make(value,index);}else{returnstatic_cast<T>(value);}}staticTmapping_at(constF&f,constT&value,longlongordinal){ifconstexpr(requires(Fg,Tx,longlongi){ActedMonoid::mapping(g,x,i);}){returnActedMonoid::mapping(f,value,ordinal);}else{returnActedMonoid::mapping(f,value);}}staticboolcan_apply_at(constF&f,constT&value,longlongordinal){ifconstexpr(requires(Fg,Tx,longlongi){ActedMonoid::can_apply(g,x,i);}){returnActedMonoid::can_apply(f,value,ordinal);}else{returnActedMonoid::can_apply(f,value);}}staticFshift_operator(constF&f,longlongordinal){ifconstexpr(requires(Fg,longlongi){ActedMonoid::op_shift(g,i);}){returnActedMonoid::op_shift(f,ordinal);}else{returnf;}}intbuild(intleft,intright,conststd::vector<T>&values)const{if(left==right)return0;if(right-left==1)returnnew_node(Node(values[left]));intmiddle=left+(right-left)/2;intleft_child=build(left,middle,values);intright_child=build(middle,right,values);returnnew_node(Node(ActedMonoid::op((*_pool)[left_child].val,(*_pool)[right_child].val),left_child,right_child));}intbuild(intleft,intright,std::vector<T>&values)const{if(left==right)return0;if(right-left==1){returnnew_node(Node(std::move(values[left])));}intmiddle=left+(right-left)/2;intleft_child=build(left,middle,values);intright_child=build(middle,right,values);returnnew_node(Node(ActedMonoid::op((*_pool)[left_child].val,(*_pool)[right_child].val),left_child,right_child));}template<typenameU>intbuild_from_values(intleft,intright,conststd::vector<U>&values)const{if(left==right)return0;if(right-left==1){returnnew_node(Node(make_value(values[left],left)));}intmiddle=left+(right-left)/2;intleft_child=build_from_values(left,middle,values);intright_child=build_from_values(middle,right,values);returnnew_node(Node(ActedMonoid::op((*_pool)[left_child].val,(*_pool)[right_child].val),left_child,right_child));}voidupdate(intnode)const{Node¤t=(*_pool)[node];current.val=ActedMonoid::op((*_pool)[current.left].val,(*_pool)[current.right].val);}intall_apply_clone(intnode,intleft,intright,constF&f,boolcopy_on_write=false)const{intresult=copy_on_write?_pool->clone_if_shared(node):clone_node(node);Node¤t=(*_pool)[result];if(can_apply_at(f,current.val,0)){current.val=mapping_at(f,current.val,0);if(right-left>1){current.lazy=ActedMonoid::op_comp(f,current.lazy);current.has_lazy=true;}returnresult;}assert(right-left>1);push(result,left,right,copy_on_write);intmiddle=left+(right-left)/2;intleft_child=all_apply_clone((*_pool)[result].left,left,middle,f,copy_on_write);intright_child=all_apply_clone((*_pool)[result].right,middle,right,shift_operator(f,middle-left),copy_on_write);_pool->replace((*_pool)[result].left,left_child);_pool->replace((*_pool)[result].right,right_child);update(result);returnresult;}voidpush(intnode,intleft,intright,boolcopy_on_write=false)const{if(!(*_pool)[node].has_lazy)return;assert(right-left>1);Flazy=(*_pool)[node].lazy;intmiddle=left+(right-left)/2;intleft_child=all_apply_clone((*_pool)[node].left,left,middle,lazy,copy_on_write);intright_child=all_apply_clone((*_pool)[node].right,middle,right,shift_operator(lazy,middle-left),copy_on_write);_pool->replace((*_pool)[node].left,left_child);_pool->replace((*_pool)[node].right,right_child);Node¤t=(*_pool)[node];current.lazy=ActedMonoid::op_id();current.has_lazy=false;}intset_node(intnode,intleft,intright,intindex,Tvalue,boolcopy_on_write=false)const{intresult=copy_on_write?_pool->clone_if_shared(node):clone_node(node);if(right-left==1){Node¤t=(*_pool)[result];current.val=std::move(value);current.lazy=ActedMonoid::op_id();current.has_lazy=false;returnresult;}push(result,left,right,copy_on_write);intmiddle=left+(right-left)/2;if(index<middle){intchild=set_node((*_pool)[result].left,left,middle,index,std::move(value),copy_on_write);_pool->replace((*_pool)[result].left,child);}else{intchild=set_node((*_pool)[result].right,middle,right,index,std::move(value),copy_on_write);_pool->replace((*_pool)[result].right,child);}update(result);returnresult;}intapply_node(intnode,intleft,intright,intquery_left,intquery_right,constF&f,boolcopy_on_write=false)const{if(query_right<=left||right<=query_left)returnnode;if(query_left<=left&&right<=query_right){returnall_apply_clone(node,left,right,shift_operator(f,left-query_left),copy_on_write);}intresult=copy_on_write?_pool->clone_if_shared(node):clone_node(node);push(result,left,right,copy_on_write);intmiddle=left+(right-left)/2;intleft_child=apply_node((*_pool)[result].left,left,middle,query_left,query_right,f,copy_on_write);intright_child=apply_node((*_pool)[result].right,middle,right,query_left,query_right,f,copy_on_write);_pool->replace((*_pool)[result].left,left_child);_pool->replace((*_pool)[result].right,right_child);update(result);returnresult;}intcopy_range_node(inttarget,intsource,intleft,intright,intquery_left,intquery_right)const{if(query_right<=left||right<=query_left)returntarget;if(query_left<=left&&right<=query_right)returnsource;intresult=clone_node(target);intmaterialized_source=clone_node(source);_pool->retain(materialized_source);push(result,left,right);push(materialized_source,left,right);intmiddle=left+(right-left)/2;intleft_child=copy_range_node((*_pool)[result].left,(*_pool)[materialized_source].left,left,middle,query_left,query_right);intright_child=copy_range_node((*_pool)[result].right,(*_pool)[materialized_source].right,middle,right,query_left,query_right);_pool->replace((*_pool)[result].left,left_child);_pool->replace((*_pool)[result].right,right_child);update(result);_pool->release(materialized_source);returnresult;}Fcompose_for_child(constF&inherited,constNode&node,longlongordinal)const{Fshifted=shift_operator(inherited,ordinal);if(!node.has_lazy)returnshifted;returnActedMonoid::op_comp(shifted,shift_operator(node.lazy,ordinal));}Tevaluate_node(intnode,intleft,intright,constF&inherited)const{constNode¤t=(*_pool)[node];if(can_apply_at(inherited,current.val,0)){returnmapping_at(inherited,current.val,0);}assert(right-left>1);intmiddle=left+(right-left)/2;returnActedMonoid::op(evaluate_node(current.left,left,middle,compose_for_child(inherited,current,0)),evaluate_node(current.right,middle,right,compose_for_child(inherited,current,middle-left)));}Tprod_node(intnode,intleft,intright,intquery_left,intquery_right,constF&inherited)const{if(query_right<=left||right<=query_left){returnActedMonoid::id();}if(query_left<=left&&right<=query_right){returnevaluate_node(node,left,right,inherited);}constNode¤t=(*_pool)[node];intmiddle=left+(right-left)/2;returnActedMonoid::op(prod_node(current.left,left,middle,query_left,query_right,compose_for_child(inherited,current,0)),prod_node(current.right,middle,right,query_left,query_right,compose_for_child(inherited,current,middle-left)));}voidcollect_node(intnode,intleft,intright,intquery_left,intquery_right,constF&inherited,std::vector<T>&result)const{if(query_right<=left||right<=query_left)return;constNode¤t=(*_pool)[node];if(right-left==1){result.push_back(mapping_at(inherited,current.val,0));return;}intmiddle=left+(right-left)/2;collect_node(current.left,left,middle,query_left,query_right,compose_for_child(inherited,current,0),result);collect_node(current.right,middle,right,query_left,query_right,compose_for_child(inherited,current,middle-left),result);}template<classPredicate>intmax_right_node(intnode,intleft,intright,intquery_left,T&product,constF&inherited,Predicate&predicate)const{if(right<=query_left)returnright;if(query_left<=left){Tnext=ActedMonoid::op(product,evaluate_node(node,left,right,inherited));if(predicate(next)){product=std::move(next);returnright;}if(right-left==1)returnleft;}constNode¤t=(*_pool)[node];intmiddle=left+(right-left)/2;intresult=max_right_node(current.left,left,middle,query_left,product,compose_for_child(inherited,current,0),predicate);if(result<middle)returnresult;returnmax_right_node(current.right,middle,right,query_left,product,compose_for_child(inherited,current,middle-left),predicate);}template<classPredicate>intmin_left_node(intnode,intleft,intright,intquery_right,T&product,constF&inherited,Predicate&predicate)const{if(query_right<=left)returnleft;if(right<=query_right){Tnext=ActedMonoid::op(evaluate_node(node,left,right,inherited),product);if(predicate(next)){product=std::move(next);returnleft;}if(right-left==1)returnright;}constNode¤t=(*_pool)[node];intmiddle=left+(right-left)/2;intresult=min_left_node(current.right,middle,right,query_right,product,compose_for_child(inherited,current,middle-left),predicate);if(middle<result)returnresult;returnmin_left_node(current.left,left,middle,query_right,product,compose_for_child(inherited,current,0),predicate);}public:PersistentSegtreeBeats():PersistentSegtreeBeats(0){}explicitPersistentSegtreeBeats(intn):_n(n),_root(0),_pool(std::make_shared<Pool>()){assert(0<=n);if(_n>0){std::vector<T>values(_n,ActedMonoid::id());_root=build(0,_n,values);}_pool->retain(_root);}explicitPersistentSegtreeBeats(conststd::vector<T>&values):_n(int(values.size())),_root(0),_pool(std::make_shared<Pool>()){_pool->reserve(values.size()*2);if(_n>0)_root=build(0,_n,values);_pool->retain(_root);}explicitPersistentSegtreeBeats(std::vector<T>&&values):_n(int(values.size())),_root(0),_pool(std::make_shared<Pool>()){_pool->reserve(values.size()*2);if(_n>0)_root=build(0,_n,values);_pool->retain(_root);}template<typenameU>requires(!std::same_as<U,T>)&&(requires(Ux){ActedMonoid::make(x);}||requires(Ux,inti){ActedMonoid::make(x,i);}||std::convertible_to<U,T>)explicitPersistentSegtreeBeats(conststd::vector<U>&values):_n(int(values.size())),_root(0),_pool(std::make_shared<Pool>()){_pool->reserve(values.size()*2);if(_n>0)_root=build_from_values(0,_n,values);_pool->retain(_root);}PersistentSegtreeBeats(constPersistentSegtreeBeats&other):_n(other._n),_root(other._root),_pool(other._pool){if(_pool)_pool->retain(_root);}PersistentSegtreeBeats(PersistentSegtreeBeats&&other)noexcept:_n(other._n),_root(other._root),_pool(std::move(other._pool)){other._n=0;other._root=0;}PersistentSegtreeBeats&operator=(constPersistentSegtreeBeats&other){if(this==&other)return*this;if(other._pool)other._pool->retain(other._root);if(_pool)_pool->release(_root);_n=other._n;_root=other._root;_pool=other._pool;return*this;}PersistentSegtreeBeats&operator=(PersistentSegtreeBeats&&other)noexcept{if(this==&other)return*this;if(_pool)_pool->release(_root);_n=other._n;_root=other._root;_pool=std::move(other._pool);other._n=0;other._root=0;return*this;}~PersistentSegtreeBeats(){if(_pool)_pool->release(_root);}intsize()const{return_n;}boolempty()const{return_n==0;}voidrelease(){if(_pool)_pool->release(_root);_pool=std::make_shared<Pool>();_root=0;_n=0;}std::size_tnode_count()const{return_pool?_pool->size():0;}PersistentSegtreeBeatsset(intindex,Tvalue)const{assert(0<=index&&index<_n);returnPersistentSegtreeBeats(_n,set_node(_root,0,_n,index,std::move(value)),_pool);}voidset_inplace(intindex,Tvalue){assert(0<=index&&index<_n);introot=set_node(_root,0,_n,index,std::move(value),true);_pool->replace(_root,root);}Tget(intindex)const{assert(0<=index&&index<_n);returnprod(index,index+1);}Toperator[](intindex)const{returnget(index);}Tprod(intleft,intright)const{assert(0<=left&&left<=right&&right<=_n);if(left==right)returnActedMonoid::id();returnprod_node(_root,0,_n,left,right,ActedMonoid::op_id());}Tall_prod()const{return_root?(*_pool)[_root].val:ActedMonoid::id();}PersistentSegtreeBeatsapply(intindex,constF&f)const{assert(0<=index&&index<_n);returnapply(index,index+1,f);}PersistentSegtreeBeatsapply(intleft,intright,constF&f)const{assert(0<=left&&left<=right&&right<=_n);if(left==right)return*this;returnPersistentSegtreeBeats(_n,apply_node(_root,0,_n,left,right,f),_pool);}voidapply_inplace(intindex,constF&f){assert(0<=index&&index<_n);apply_inplace(index,index+1,f);}voidapply_inplace(intleft,intright,constF&f){assert(0<=left&&left<=right&&right<=_n);if(left==right)return;introot=apply_node(_root,0,_n,left,right,f,true);_pool->replace(_root,root);}PersistentSegtreeBeatscopy_range_from(constPersistentSegtreeBeats&source,intleft,intright)const{assert(_n==source._n);assert(_pool==source._pool);assert(0<=left&&left<=right&&right<=_n);if(left==right)return*this;returnPersistentSegtreeBeats(_n,copy_range_node(_root,source._root,0,_n,left,right),_pool);}std::vector<T>to_vector()const{returnto_vector(0,_n);}std::vector<T>to_vector(intleft,intright)const{assert(0<=left&&left<=right&&right<=_n);std::vector<T>result;result.reserve(right-left);if(left!=right){collect_node(_root,0,_n,left,right,ActedMonoid::op_id(),result);}returnresult;}template<classPredicate>intmax_right(intleft,Predicatepredicate)const{assert(0<=left&&left<=_n);assert(predicate(ActedMonoid::id()));if(left==_n)return_n;Tproduct=ActedMonoid::id();returnmax_right_node(_root,0,_n,left,product,ActedMonoid::op_id(),predicate);}template<classPredicate>intmin_left(intright,Predicatepredicate)const{assert(0<=right&&right<=_n);assert(predicate(ActedMonoid::id()));if(right==0)return0;Tproduct=ActedMonoid::id();returnmin_left_node(_root,0,_n,right,product,ActedMonoid::op_id(),predicate);}};}// namespace ds}// namespace m1une#endif // M1UNE_DS_PERSISTENT_SEGTREE_BEATS_HPP
#line 1 "ds/segtree/persistent_segtree_beats.hpp"
#include<cassert>
#include<concepts>
#include<cstddef>
#include<memory>
#include<utility>
#include<vector>#line 1 "beats_acted_monoid/concept.hpp"
#line 5 "beats_acted_monoid/concept.hpp"
#line 1 "acted_monoid/concept.hpp"
#line 5 "acted_monoid/concept.hpp"
namespacem1une{namespaceacted_monoid{// Concept defining the requirements for an Acted Monoid.template<typenameAM>conceptIsActedMonoid=requires(typenameAM::value_typea,typenameAM::value_typeb,typenameAM::operator_typef,typenameAM::operator_typeg){// 1. Value MonoidtypenameAM::value_type;{AM::id()}->std::same_as<typenameAM::value_type>;{AM::op(a,b)}->std::same_as<typenameAM::value_type>;// 2. Operator MonoidtypenameAM::operator_type;{AM::op_id()}->std::same_as<typenameAM::operator_type>;{AM::op_comp(f,g)}->std::same_as<typenameAM::operator_type>;// Composition order: f(g(x))// 3. Mapping: Operator x Value -> Value{AM::mapping(f,a)}->std::same_as<typenameAM::value_type>;};// Concept for acted monoids whose value monoid is a commutative group.// The value operation must obey commutativity and inverse laws.template<typenameAM>conceptIsCommutativeActedGroup=IsActedMonoid<AM>&&requires(typenameAM::value_typea){{AM::inv(a)}->std::same_as<typenameAM::value_type>;};}// namespace acted_monoid}// namespace m1une#line 7 "beats_acted_monoid/concept.hpp"
namespacem1une{namespacebeats_acted_monoid{// An acted monoid whose action may require descent before it can be applied.template<typenameAM>conceptIsBeatsActedMonoid=m1une::acted_monoid::IsActedMonoid<AM>&&requires(typenameAM::value_typex,typenameAM::operator_typef){{AM::can_apply(f,x)}->std::same_as<bool>;};}// namespace beats_acted_monoid}// namespace m1une#line 1 "ds/segtree/persistent_node_pool.hpp"
#line 6 "ds/segtree/persistent_node_pool.hpp"
#include<limits>
#line 9 "ds/segtree/persistent_node_pool.hpp"
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#line 13 "ds/segtree/persistent_segtree_beats.hpp"
namespacem1une{namespaceds{// A persistent Segment Tree Beats for fallible monoid actions.template<m1une::beats_acted_monoid::IsBeatsActedMonoidActedMonoid>structPersistentSegtreeBeats{usingvalue_type=typenameActedMonoid::value_type;usingoperator_type=typenameActedMonoid::operator_type;usingT=value_type;usingF=operator_type;private:structNode{Tval;Flazy;intleft;intright;intreferences;boolhas_lazy;Node():val(ActedMonoid::id()),lazy(ActedMonoid::op_id()),left(0),right(0),references(0),has_lazy(false){}explicitNode(Tvalue):val(std::move(value)),lazy(ActedMonoid::op_id()),left(0),right(0),references(0),has_lazy(false){}Node(Tvalue,intleft_child,intright_child):val(std::move(value)),lazy(ActedMonoid::op_id()),left(left_child),right(right_child),references(0),has_lazy(false){}};usingPool=detail::PersistentNodePool<Node>;int_n;int_root;std::shared_ptr<Pool>_pool;explicitPersistentSegtreeBeats(intn,introot,std::shared_ptr<Pool>pool):_n(n),_root(root),_pool(std::move(pool)){_pool->retain(_root);}intnew_node(constNode&node)const{return_pool->emplace(node);}intnew_node(Node&&node)const{return_pool->emplace(std::move(node));}intclone_node(intnode)const{return_pool->clone(node);}template<typenameU>staticTmake_value(constU&value,intindex){ifconstexpr(requires(Ux){ActedMonoid::make(x);}){returnActedMonoid::make(value);}elseifconstexpr(requires(Ux,inti){ActedMonoid::make(x,i);}){returnActedMonoid::make(value,index);}else{returnstatic_cast<T>(value);}}staticTmapping_at(constF&f,constT&value,longlongordinal){ifconstexpr(requires(Fg,Tx,longlongi){ActedMonoid::mapping(g,x,i);}){returnActedMonoid::mapping(f,value,ordinal);}else{returnActedMonoid::mapping(f,value);}}staticboolcan_apply_at(constF&f,constT&value,longlongordinal){ifconstexpr(requires(Fg,Tx,longlongi){ActedMonoid::can_apply(g,x,i);}){returnActedMonoid::can_apply(f,value,ordinal);}else{returnActedMonoid::can_apply(f,value);}}staticFshift_operator(constF&f,longlongordinal){ifconstexpr(requires(Fg,longlongi){ActedMonoid::op_shift(g,i);}){returnActedMonoid::op_shift(f,ordinal);}else{returnf;}}intbuild(intleft,intright,conststd::vector<T>&values)const{if(left==right)return0;if(right-left==1)returnnew_node(Node(values[left]));intmiddle=left+(right-left)/2;intleft_child=build(left,middle,values);intright_child=build(middle,right,values);returnnew_node(Node(ActedMonoid::op((*_pool)[left_child].val,(*_pool)[right_child].val),left_child,right_child));}intbuild(intleft,intright,std::vector<T>&values)const{if(left==right)return0;if(right-left==1){returnnew_node(Node(std::move(values[left])));}intmiddle=left+(right-left)/2;intleft_child=build(left,middle,values);intright_child=build(middle,right,values);returnnew_node(Node(ActedMonoid::op((*_pool)[left_child].val,(*_pool)[right_child].val),left_child,right_child));}template<typenameU>intbuild_from_values(intleft,intright,conststd::vector<U>&values)const{if(left==right)return0;if(right-left==1){returnnew_node(Node(make_value(values[left],left)));}intmiddle=left+(right-left)/2;intleft_child=build_from_values(left,middle,values);intright_child=build_from_values(middle,right,values);returnnew_node(Node(ActedMonoid::op((*_pool)[left_child].val,(*_pool)[right_child].val),left_child,right_child));}voidupdate(intnode)const{Node¤t=(*_pool)[node];current.val=ActedMonoid::op((*_pool)[current.left].val,(*_pool)[current.right].val);}intall_apply_clone(intnode,intleft,intright,constF&f,boolcopy_on_write=false)const{intresult=copy_on_write?_pool->clone_if_shared(node):clone_node(node);Node¤t=(*_pool)[result];if(can_apply_at(f,current.val,0)){current.val=mapping_at(f,current.val,0);if(right-left>1){current.lazy=ActedMonoid::op_comp(f,current.lazy);current.has_lazy=true;}returnresult;}assert(right-left>1);push(result,left,right,copy_on_write);intmiddle=left+(right-left)/2;intleft_child=all_apply_clone((*_pool)[result].left,left,middle,f,copy_on_write);intright_child=all_apply_clone((*_pool)[result].right,middle,right,shift_operator(f,middle-left),copy_on_write);_pool->replace((*_pool)[result].left,left_child);_pool->replace((*_pool)[result].right,right_child);update(result);returnresult;}voidpush(intnode,intleft,intright,boolcopy_on_write=false)const{if(!(*_pool)[node].has_lazy)return;assert(right-left>1);Flazy=(*_pool)[node].lazy;intmiddle=left+(right-left)/2;intleft_child=all_apply_clone((*_pool)[node].left,left,middle,lazy,copy_on_write);intright_child=all_apply_clone((*_pool)[node].right,middle,right,shift_operator(lazy,middle-left),copy_on_write);_pool->replace((*_pool)[node].left,left_child);_pool->replace((*_pool)[node].right,right_child);Node¤t=(*_pool)[node];current.lazy=ActedMonoid::op_id();current.has_lazy=false;}intset_node(intnode,intleft,intright,intindex,Tvalue,boolcopy_on_write=false)const{intresult=copy_on_write?_pool->clone_if_shared(node):clone_node(node);if(right-left==1){Node¤t=(*_pool)[result];current.val=std::move(value);current.lazy=ActedMonoid::op_id();current.has_lazy=false;returnresult;}push(result,left,right,copy_on_write);intmiddle=left+(right-left)/2;if(index<middle){intchild=set_node((*_pool)[result].left,left,middle,index,std::move(value),copy_on_write);_pool->replace((*_pool)[result].left,child);}else{intchild=set_node((*_pool)[result].right,middle,right,index,std::move(value),copy_on_write);_pool->replace((*_pool)[result].right,child);}update(result);returnresult;}intapply_node(intnode,intleft,intright,intquery_left,intquery_right,constF&f,boolcopy_on_write=false)const{if(query_right<=left||right<=query_left)returnnode;if(query_left<=left&&right<=query_right){returnall_apply_clone(node,left,right,shift_operator(f,left-query_left),copy_on_write);}intresult=copy_on_write?_pool->clone_if_shared(node):clone_node(node);push(result,left,right,copy_on_write);intmiddle=left+(right-left)/2;intleft_child=apply_node((*_pool)[result].left,left,middle,query_left,query_right,f,copy_on_write);intright_child=apply_node((*_pool)[result].right,middle,right,query_left,query_right,f,copy_on_write);_pool->replace((*_pool)[result].left,left_child);_pool->replace((*_pool)[result].right,right_child);update(result);returnresult;}intcopy_range_node(inttarget,intsource,intleft,intright,intquery_left,intquery_right)const{if(query_right<=left||right<=query_left)returntarget;if(query_left<=left&&right<=query_right)returnsource;intresult=clone_node(target);intmaterialized_source=clone_node(source);_pool->retain(materialized_source);push(result,left,right);push(materialized_source,left,right);intmiddle=left+(right-left)/2;intleft_child=copy_range_node((*_pool)[result].left,(*_pool)[materialized_source].left,left,middle,query_left,query_right);intright_child=copy_range_node((*_pool)[result].right,(*_pool)[materialized_source].right,middle,right,query_left,query_right);_pool->replace((*_pool)[result].left,left_child);_pool->replace((*_pool)[result].right,right_child);update(result);_pool->release(materialized_source);returnresult;}Fcompose_for_child(constF&inherited,constNode&node,longlongordinal)const{Fshifted=shift_operator(inherited,ordinal);if(!node.has_lazy)returnshifted;returnActedMonoid::op_comp(shifted,shift_operator(node.lazy,ordinal));}Tevaluate_node(intnode,intleft,intright,constF&inherited)const{constNode¤t=(*_pool)[node];if(can_apply_at(inherited,current.val,0)){returnmapping_at(inherited,current.val,0);}assert(right-left>1);intmiddle=left+(right-left)/2;returnActedMonoid::op(evaluate_node(current.left,left,middle,compose_for_child(inherited,current,0)),evaluate_node(current.right,middle,right,compose_for_child(inherited,current,middle-left)));}Tprod_node(intnode,intleft,intright,intquery_left,intquery_right,constF&inherited)const{if(query_right<=left||right<=query_left){returnActedMonoid::id();}if(query_left<=left&&right<=query_right){returnevaluate_node(node,left,right,inherited);}constNode¤t=(*_pool)[node];intmiddle=left+(right-left)/2;returnActedMonoid::op(prod_node(current.left,left,middle,query_left,query_right,compose_for_child(inherited,current,0)),prod_node(current.right,middle,right,query_left,query_right,compose_for_child(inherited,current,middle-left)));}voidcollect_node(intnode,intleft,intright,intquery_left,intquery_right,constF&inherited,std::vector<T>&result)const{if(query_right<=left||right<=query_left)return;constNode¤t=(*_pool)[node];if(right-left==1){result.push_back(mapping_at(inherited,current.val,0));return;}intmiddle=left+(right-left)/2;collect_node(current.left,left,middle,query_left,query_right,compose_for_child(inherited,current,0),result);collect_node(current.right,middle,right,query_left,query_right,compose_for_child(inherited,current,middle-left),result);}template<classPredicate>intmax_right_node(intnode,intleft,intright,intquery_left,T&product,constF&inherited,Predicate&predicate)const{if(right<=query_left)returnright;if(query_left<=left){Tnext=ActedMonoid::op(product,evaluate_node(node,left,right,inherited));if(predicate(next)){product=std::move(next);returnright;}if(right-left==1)returnleft;}constNode¤t=(*_pool)[node];intmiddle=left+(right-left)/2;intresult=max_right_node(current.left,left,middle,query_left,product,compose_for_child(inherited,current,0),predicate);if(result<middle)returnresult;returnmax_right_node(current.right,middle,right,query_left,product,compose_for_child(inherited,current,middle-left),predicate);}template<classPredicate>intmin_left_node(intnode,intleft,intright,intquery_right,T&product,constF&inherited,Predicate&predicate)const{if(query_right<=left)returnleft;if(right<=query_right){Tnext=ActedMonoid::op(evaluate_node(node,left,right,inherited),product);if(predicate(next)){product=std::move(next);returnleft;}if(right-left==1)returnright;}constNode¤t=(*_pool)[node];intmiddle=left+(right-left)/2;intresult=min_left_node(current.right,middle,right,query_right,product,compose_for_child(inherited,current,middle-left),predicate);if(middle<result)returnresult;returnmin_left_node(current.left,left,middle,query_right,product,compose_for_child(inherited,current,0),predicate);}public:PersistentSegtreeBeats():PersistentSegtreeBeats(0){}explicitPersistentSegtreeBeats(intn):_n(n),_root(0),_pool(std::make_shared<Pool>()){assert(0<=n);if(_n>0){std::vector<T>values(_n,ActedMonoid::id());_root=build(0,_n,values);}_pool->retain(_root);}explicitPersistentSegtreeBeats(conststd::vector<T>&values):_n(int(values.size())),_root(0),_pool(std::make_shared<Pool>()){_pool->reserve(values.size()*2);if(_n>0)_root=build(0,_n,values);_pool->retain(_root);}explicitPersistentSegtreeBeats(std::vector<T>&&values):_n(int(values.size())),_root(0),_pool(std::make_shared<Pool>()){_pool->reserve(values.size()*2);if(_n>0)_root=build(0,_n,values);_pool->retain(_root);}template<typenameU>requires(!std::same_as<U,T>)&&(requires(Ux){ActedMonoid::make(x);}||requires(Ux,inti){ActedMonoid::make(x,i);}||std::convertible_to<U,T>)explicitPersistentSegtreeBeats(conststd::vector<U>&values):_n(int(values.size())),_root(0),_pool(std::make_shared<Pool>()){_pool->reserve(values.size()*2);if(_n>0)_root=build_from_values(0,_n,values);_pool->retain(_root);}PersistentSegtreeBeats(constPersistentSegtreeBeats&other):_n(other._n),_root(other._root),_pool(other._pool){if(_pool)_pool->retain(_root);}PersistentSegtreeBeats(PersistentSegtreeBeats&&other)noexcept:_n(other._n),_root(other._root),_pool(std::move(other._pool)){other._n=0;other._root=0;}PersistentSegtreeBeats&operator=(constPersistentSegtreeBeats&other){if(this==&other)return*this;if(other._pool)other._pool->retain(other._root);if(_pool)_pool->release(_root);_n=other._n;_root=other._root;_pool=other._pool;return*this;}PersistentSegtreeBeats&operator=(PersistentSegtreeBeats&&other)noexcept{if(this==&other)return*this;if(_pool)_pool->release(_root);_n=other._n;_root=other._root;_pool=std::move(other._pool);other._n=0;other._root=0;return*this;}~PersistentSegtreeBeats(){if(_pool)_pool->release(_root);}intsize()const{return_n;}boolempty()const{return_n==0;}voidrelease(){if(_pool)_pool->release(_root);_pool=std::make_shared<Pool>();_root=0;_n=0;}std::size_tnode_count()const{return_pool?_pool->size():0;}PersistentSegtreeBeatsset(intindex,Tvalue)const{assert(0<=index&&index<_n);returnPersistentSegtreeBeats(_n,set_node(_root,0,_n,index,std::move(value)),_pool);}voidset_inplace(intindex,Tvalue){assert(0<=index&&index<_n);introot=set_node(_root,0,_n,index,std::move(value),true);_pool->replace(_root,root);}Tget(intindex)const{assert(0<=index&&index<_n);returnprod(index,index+1);}Toperator[](intindex)const{returnget(index);}Tprod(intleft,intright)const{assert(0<=left&&left<=right&&right<=_n);if(left==right)returnActedMonoid::id();returnprod_node(_root,0,_n,left,right,ActedMonoid::op_id());}Tall_prod()const{return_root?(*_pool)[_root].val:ActedMonoid::id();}PersistentSegtreeBeatsapply(intindex,constF&f)const{assert(0<=index&&index<_n);returnapply(index,index+1,f);}PersistentSegtreeBeatsapply(intleft,intright,constF&f)const{assert(0<=left&&left<=right&&right<=_n);if(left==right)return*this;returnPersistentSegtreeBeats(_n,apply_node(_root,0,_n,left,right,f),_pool);}voidapply_inplace(intindex,constF&f){assert(0<=index&&index<_n);apply_inplace(index,index+1,f);}voidapply_inplace(intleft,intright,constF&f){assert(0<=left&&left<=right&&right<=_n);if(left==right)return;introot=apply_node(_root,0,_n,left,right,f,true);_pool->replace(_root,root);}PersistentSegtreeBeatscopy_range_from(constPersistentSegtreeBeats&source,intleft,intright)const{assert(_n==source._n);assert(_pool==source._pool);assert(0<=left&&left<=right&&right<=_n);if(left==right)return*this;returnPersistentSegtreeBeats(_n,copy_range_node(_root,source._root,0,_n,left,right),_pool);}std::vector<T>to_vector()const{returnto_vector(0,_n);}std::vector<T>to_vector(intleft,intright)const{assert(0<=left&&left<=right&&right<=_n);std::vector<T>result;result.reserve(right-left);if(left!=right){collect_node(_root,0,_n,left,right,ActedMonoid::op_id(),result);}returnresult;}template<classPredicate>intmax_right(intleft,Predicatepredicate)const{assert(0<=left&&left<=_n);assert(predicate(ActedMonoid::id()));if(left==_n)return_n;Tproduct=ActedMonoid::id();returnmax_right_node(_root,0,_n,left,product,ActedMonoid::op_id(),predicate);}template<classPredicate>intmin_left(intright,Predicatepredicate)const{assert(0<=right&&right<=_n);assert(predicate(ActedMonoid::id()));if(right==0)return0;Tproduct=ActedMonoid::id();returnmin_left_node(_root,0,_n,right,product,ActedMonoid::op_id(),predicate);}};}// namespace ds}// namespace m1une