#pragma once
template<classMonoid>structSplayTree{usingT=typenameMonoid::value_type;structNode{intl,r,p,sz;boolrev;Tval,sum,revsum;};vector<Node>t;SplayTree(intreserve=0){t.reserve(reserve+1);t.push_back(Node{0,0,0,0,false,Monoid::unit(),Monoid::unit(),Monoid::unit()});}intmake(constT&v){t.push_back(Node{0,0,0,1,false,v,v,v});returnSZ(t)-1;}intsz(intx){returnt[x].sz;}Tsum(intx){returnt[x].sum;}voidpull(intx){Node&v=t[x];v.sz=t[v.l].sz+1+t[v.r].sz;v.sum=Monoid::op(Monoid::op(t[v.l].sum,v.val),t[v.r].sum);v.revsum=Monoid::op(Monoid::op(t[v.r].revsum,v.val),t[v.l].revsum);}voidtoggle(intx){if(!x)return;swap(t[x].l,t[x].r);swap(t[x].sum,t[x].revsum);t[x].rev^=1;}voidpush(intx){if(t[x].rev){toggle(t[x].l);toggle(t[x].r);t[x].rev=false;}}voidrotate(intx){intp=t[x].p,g=t[p].p;if(t[p].l==x){t[p].l=t[x].r;if(t[x].r)t[t[x].r].p=p;t[x].r=p;}else{t[p].r=t[x].l;if(t[x].l)t[t[x].l].p=p;t[x].l=p;}t[p].p=x;t[x].p=g;if(g)(t[g].l==p?t[g].l:t[g].r)=x;pull(p);}voidsplay(intx){while(intp=t[x].p){intg=t[p].p;if(g)rotate((t[g].l==p)==(t[p].l==x)?p:x);rotate(x);}pull(x);}intkth(intx,intk){assert(0<=k&&k<sz(x));while(true){push(x);intls=t[t[x].l].sz;if(k<ls)x=t[x].l;elseif(k==ls)break;elsek-=ls+1,x=t[x].r;}splay(x);returnx;}intbuild(constvector<T>&a){autorec=[&](auto&&self,intl,intr)->int{if(l>r)return0;intm=(l+r)/2,x=make(a[m]);intlc=self(self,l,m-1),rc=self(self,m+1,r);t[x].l=lc,t[x].r=rc;if(lc)t[lc].p=x;if(rc)t[rc].p=x;pull(x);returnx;};returnrec(rec,0,SZ(a)-1);}intmerge(inta,intb){if(!a||!b)returna|b;a=kth(a,sz(a)-1);t[a].r=b;t[b].p=a;pull(a);returna;}pair<int,int>split(intx,intk){if(k<=0)return{0,x};if(k>=sz(x))return{x,0};x=kth(x,k-1);inty=t[x].r;t[x].r=0;t[y].p=0;pull(x);return{x,y};}Tquery(int&x,intl,intr){if(l>r)returnMonoid::unit();auto[a,b]=split(x,l);auto[c,d]=split(b,r-l+1);Tres=sum(c);x=merge(a,merge(c,d));returnres;}voidreverse(int&x,intl,intr){if(l>=r)return;auto[a,b]=split(x,l);auto[c,d]=split(b,r-l+1);toggle(c);x=merge(a,merge(c,d));}Tget(int&x,intk){x=kth(x,k);returnt[x].val;}voidset(int&x,intk,constT&v){x=kth(x,k);t[x].val=v;pull(x);}voidinsert(int&x,intk,constT&v){auto[a,b]=split(x,k);x=merge(merge(a,make(v)),b);}voiderase(int&x,intk){auto[a,b]=split(x,k);auto[c,d]=split(b,1);x=merge(a,d);}};