#pragma once
#include<cstdint>namespacehaar_lib{template<typenameMonoid>classdynamic_segment_tree{public:usingvalue_type=typenameMonoid::value_type;private:structnode{value_typeval;node*left=nullptr,*right=nullptr;node(constvalue_type&val):val(val){}};MonoidM_;int64_tdepth_,size_,hsize_;node*root_=nullptr;value_typeeval(node*t)const{returnt?t->val:M_();}node*update(node*t,int64_tl,int64_tr,int64_tpos,constvalue_type&val){if(r-l==1){if(t)t->val=val;elset=newnode(val);}else{constint64_tm=(l+r)/2;if(nott)t=newnode(val);if(pos<m)t->left=update(t->left,l,m,pos,val);elset->right=update(t->right,m,r,pos,val);t->val=M_(eval(t->left),eval(t->right));}returnt;}value_typeget(node*t,int64_tl,int64_tr,int64_tx,int64_ty)const{if(nott)returnM_();if(x<=landr<=y)returnt?t->val:M_();if(r<xory<l)returnM_();int64_tm=(l+r)>>1;returnM_(get(t->left,l,m,x,y),get(t->right,m,r,x,y));}public:dynamic_segment_tree(){}dynamic_segment_tree(int64_tn):depth_(n>1?64-__builtin_clzll(n-1)+1:1),size_(1LL<<depth_),hsize_(size_/2){root_=newnode(M_());}voidset(int64_ti,constvalue_type&x){update(root_,0,hsize_,i,x);}voidupdate(int64_ti,constvalue_type&x){set(i,M_((*this)[i],x));}value_typefold(int64_tl,int64_tr)const{returnget(root_,0,hsize_,l,r);}value_typeoperator[](int64_ti)const{returnfold(i,i+1);}};}// namespace haar_lib