#pragma once
#include<tuple>
template<typenameNode>structAVL_base{usingnp=Node*;intsz(npt){returnt?t->sz:0;}intdep(npt){returnt?t->dep:0;}npupdate(npt){t->sz=sz(t->ch[0])+1+sz(t->ch[1]);t->dep=std::max(dep(t->ch[0]),dep(t->ch[1]))+1;returnt;}npmerge_with_root(nps,npt,npu){if(abs(sz(s)-sz(u))<2){t->ch[0]=s;t->ch[1]=u;returnupdate(t);}if(sz(s)>sz(u)){s->ch[1]=merge_with_root(s->ch[1],t,u);returnupdate(s);}else{u->ch[0]=merge_with_root(s,t,u->ch[0]);returnupdate(t);}}npmake_root(np&t){if(t->ch[1]){npres=make_root(t->ch[1]);update(t);returnres;}else{npres=t;t=t->ch[0];returnres;}}npmerge(nps,npt){if(!s||!t)returns?s:t;npu=make_root(s);returnmerge_with_root(s,u,t);}std::pair<np,np>split(npt,inti){if(!t)returnstd::make_pair(0,0);nps=t->ch[0],u=t->ch[1];t->ch[0]=0;t->ch[1]=0;if(i==sz(s)){returnmake_pair(s,merge_with_root(0,t,u));}if(i<sz(s)){autor=split(s,i);returnmake_pair(r.first,merge_with_root(r.second,t,u));}else{autor=split(u,i-sz(s)-1);returnmake_pair(merge_with_root(s,t,r.first),r.second);}}//insert erasevoidinsert(constnp&x,np&t){if(!t)t=x;elseif(*x<=*t)insert(x,t->ch[1]);elseinsert(x,t->ch[0]);t=balance(update(t));}boolerase(constnp&x,np&t){if(!t)returnfalse;elseif(*x==*t){if(!t->ch[0]||!t->ch[1])t=t->ch[0]?t->ch[0]:t->ch[1];elsemove_down(t->ch[0],t);returntrue;}boolb;if(*x<*t)b=erase(x,t->ch[0]);elseb=erase(x,t->ch[1]);t=balance(update(t));returnb;}voidmove_down(np&t,np&p){if(t->ch[1])move_down(t->ch[1],p);elsep->val=t->val,t=t->ch[0];t=balance(update(t));}nprot(npt){intb=dep(t->ch[0])<dep(t->ch[1]);if(dep(t->ch[0])==dep(t->ch[1]))returnt;nps=t->ch[b];t->ch[b]=s->ch[1-b];s->ch[1-b]=t;update(t);update(s);returns;}npbalance(npt){if(abs(dep(t->ch[0])-dep(t->ch[1]))!=2)returnt;boolb=dep(t->ch[0])<dep(t->ch[1]);if(t->ch[b]&&dep(t->ch[b]->ch[b])<dep(t->ch[b]->ch[1-b])){t->ch[b]=rot(t->ch[b]);}returnrot(update(t));}};