分块
template<typename T,int maxn>struct block_array{
int bn,bp[maxn],bl[maxn],br[maxn],len[maxn];
T v[maxn],tag[maxn];
void build(int n,T a[]){
bn=sqrt(n);
for(int i=1;i<=bn;i++)bl[i]=n/bn*(i-1)+1,br[i]=n/bn*i;
br[bn]=n;
for(int i=1;i<=bn;i++)len[i]=br[i]-bl[i]+1;
for(int i=1;i<=bn;i++)for(int j=bl[i];j<=br[i];j++)bp[j]=i,v[i]+=a[j];
}
void add(int l,int r,T x){
if(bp[l]==bp[r])for(int i=l;i<=r;i++)a[i]+=x,v[bp[i]]+=x;
else{
for(int i=l;i<=br[bp[l]];i++)a[i]+=x,v[bp[i]]+=x;
for(int i=bp[l]+1;i<bp[r];i++)tag[i]+=x;
for(int i=bl[bp[r]];i<=r;i++)a[i]+=x,v[bp[i]]+=x;
}
}
T query(int l,int r,T ans=0){
if(bp[l]==bp[r])for(int i=l;i<=r;i++)ans+=a[i]+tag[bp[i]];
else{
for(int i=l;i<=br[bp[l]];i++)ans+=a[i]+tag[bp[i]];
for(int i=bp[l]+1;i<bp[r];i++)ans+=v[i]+tag[i]*len[i];
for(int i=bl[bp[r]];i<=r;i++)ans+=a[i]+tag[bp[i]];
}
return ans;
}
};
线段树
template<typename T>struct node{
T v,tag;
};
template<typename T,int maxn>struct SMT{
node<T>tr[maxn];
void pushdown(int pos,int nl,int nr){
int mid=(nl+nr)>>1;
tr[pos<<1].tag+=tr[pos].tag,tr[pos<<1|1].tag+=tr[pos].tag;
tr[pos<<1].v+=(mid-nl+1)*tr[pos].tag,tr[pos<<1|1].v+=(nr-mid)*tr[pos].tag;
tr[pos].tag=0;
}
void pushup(int pos){
tr[pos].v=tr[pos<<1].v+tr[pos<<1|1].v;
}
void build(int pos,int nl,int nr,T a[]){
tr[pos].tag=0;
if(nl==nr)tr[pos].v=a[nl];
else{
int mid=(nl+nr)>>1;
build(pos<<1,nl,mid,a),build(pos<<1|1,mid+1,nr,a),pushup(pos);
}
}
void add(int pos,int nl,int nr,int gl,int gr,T k){
if(gl>gr)return;
if(gl<=nl&&nr<=gr){
tr[pos].tag+=k;
tr[pos].v+=(nr-nl+1)*k;
return;
}
pushdown(pos,nl,nr);
int mid=(nl+nr)>>1;
if(gl<=mid)add(pos<<1,nl,mid,gl,gr,k);
if(gr>mid)add(pos<<1|1,mid+1,nr,gl,gr,k);
pushup(pos);
}
T query(int pos,int nl,int nr,int gl,int gr){
if(gl>gr)return 0;
if(gl<=nl&&nr<=gr)return tr[pos].v;
pushdown(pos,nl,nr);
int mid=(nl+nr)>>1;
T ans=0;
if(gl<=mid)ans+=query(pos<<1,nl,mid,gl,gr);
if(gr>mid)ans+=query(pos<<1|1,mid+1,nr,gl,gr);
return ans;
}
};
主席树
template<typename T>struct node{
T v;
int ls,rs;
};
template<typename T,int maxn>struct SMT{
node<T>tr[maxn];
int cnt;
void build(int &pos,int nl,int nr,T a[]){
pos=++cnt;
if(nl==nr)tr[pos].v=a[nl];
else{
int mid=(nl+nr)>>1;
build(tr[pos].ls,nl,mid,a),build(tr[pos].rs,mid+1,nr,a);
}
}
void add(int &pos,int v,int nl,int nr,int g,T k){
tr[pos=++cnt]=tr[v];
if(nl==nr){
tr[pos].v=k;
return;
}
int mid=(nl+nr)>>1;
if(g<=mid)add(tr[pos].ls,tr[v].ls,nl,mid,g,k);
else add(tr[pos].rs,tr[v].rs,mid+1,nr,g,k);
}
T query(int pos,int nl,int nr,int g){
if(nl==nr)return tr[pos].v;
int mid=(nl+nr)>>1;
if(g<=mid)return query(tr[pos].ls,nl,mid,g);
else return query(tr[pos].rs,mid+1,nr,g);
}
};
李超线段树
template<int maxn>struct SMT{
int tr[maxn],cnt;
double k[maxn],b[maxn];
bool check(int u,int v,int x){
return fabs(k[u]*x+b[u]-k[v]*x-b[v])<1e-6?u<v:k[u]*x+b[u]>k[v]*x+b[v];
}
void add(int pos,int nl,int nr,int gl,int gr,int g){
int mid=(nl+nr)>>1;
if(gl<=nl&&nr<=gr){
if(check(tr[pos],g,nl)&&check(tr[pos],g,nr))return;
if(check(g,tr[pos],nl)&&check(g,tr[pos],nr)){
tr[pos]=g;
return;
}
if(check(g,tr[pos],mid))swap(g,tr[pos]);
if(check(g,tr[pos],nl))add(pos<<1,nl,mid,gl,gr,g);
else add(pos<<1|1,mid+1,nr,gl,gr,g);
return;
}
if(gl<=mid)add(pos<<1,nl,mid,gl,gr,g);
if(gr>mid)add(pos<<1|1,mid+1,nr,gl,gr,g);
}
void insert(int pos,int nl,int nr,double k,double b){
(*this).k[++cnt]=k,(*this).b[cnt]=b,add(pos,1,39989,nl,nr,cnt);
}
double query(int pos,int nl,int nr,int g){
if(nl==nr)return tr[pos];
int mid=(nl+nr)>>1,ans;
if(g<=mid)ans=query(pos<<1,nl,mid,g);
else ans=query(pos<<1|1,mid+1,nr,g);
if(check(tr[pos],ans,g))return tr[pos];
else return ans;
}
};
树状数组
template<typename T,int maxn>struct BIT{
T tr[maxn];
void build(int n,T a[]){
for(int i=1;i<=n;i++){
tr[i]+=a[i];
if(i+(i&-i)<=n)tr[i+(i&-i)]+=tr[i];
}
}
void add(int x,T k){
for(;x<=n;x+=(x&-x))tr[x]+=k;
}
T query(int x,T ans=0){
for(;x;x-=(x&-x))ans+=tr[x];
return ans;
}
};
并查集
template<int maxn>struct DSU{
int f[maxn],s[maxn];
void build(int n){
for(int i=1;i<=n;i++)s[i]=1;
}
void clear(){
memset(f,0,sizeof(f)),memset(s,0,sizeof(s));
}
int find(int x)
{
return f[x]?find(f[x]):x;
}
bool merge(int x,int y){
int f1=find(x),f2=find(y);
if(f1==f2)return 0;
if(s[f1]<s[f2])f[f1]=f2,s[f2]+=s[f1];
else f[f2]=f1,s[f1]+=s[f2];
return 1;
}
};
可持久化并查集
struct node{
int f,s,ls,rs;
};
template<int maxn>struct DSU{
node tr[maxn];
int cnt;
void build(int &pos,int nl,int nr){
pos=++cnt;
if(nl==nr)tr[pos].s=1;
else{
int mid=(nl+nr)>>1;
build(tr[pos].ls,nl,mid),build(tr[pos].rs,mid+1,nr);
}
}
int query(int pos,int nl,int nr,int g){
if(nl==nr)return pos;
int mid=(nl+nr)>>1;
if(g<=mid)return query(tr[pos].ls,nl,mid,g);
else return query(tr[pos].rs,mid+1,nr,g);
}
int find(int pos,int nl,int nr,int x){
int f=tr[query(pos,nl,nr,x)].f;
return f?find(pos,nl,nr,f):x;
}
void add(int &pos,int v,int nl,int nr,int g,int k,bool f){
tr[pos=++cnt]=tr[v];
if(nl==nr){
f?tr[pos].s+=k:tr[pos].f=k;
return;
}
int mid=(nl+nr)>>1;
if(g<=mid)add(tr[pos].ls,tr[v].ls,nl,mid,g,k,f);
else add(tr[pos].rs,tr[v].rs,mid+1,nr,g,k,f);
}
bool merge(int &pos,int v,int nl,int nr,int x,int y){
int f1=find(v,nl,nr,x),f2=find(v,nl,nr,y),s1=tr[query(v,nl,nr,f1)].s,s2=tr[query(v,nl,nr,f2)].s;
if(f1==f2)return 0;
int temp=0;
if(s1<s2)add(temp,v,nl,nr,f1,f2,0),add(pos,temp,nl,nr,f2,s1,1);
else add(temp,v,nl,nr,f2,f1,0),add(pos,temp,nl,nr,f1,s2,1);
return 1;
}
};
ST表
template<typename T,int maxn1,int maxn2>struct ST{
T st[maxn1][maxn2];
int lg[maxn1];
void build(int n,T a[]){
for(int i=2;i<=n;i++)lg[i]=lg[i>>1]+1;
for(int i=1;i<=n;i++)st[i][0]=a[i];
for(int j=1;1<<j<=n;j++)for(int i=1;i+(1<<j)-1<=n;i++)st[i][j]=max(st[i][j-1],st[i+(1<<(j-1))][j-1]);
}
T query(int l,int r){
return max(st[l][lg[r-l+1]],st[r-(1<<lg[r-l+1])+1][lg[r-l+1]]);
}
};
珂朵莉树
template<typename T>struct node{
int l,r;
mutable T v;
bool operator<(node a)const{
return l<a.l;
}
};
template<typename T>struct chtholly_tree{
set<node<T>>tr;
void build(int n,T a[]){
for(int i=1;i<=n;i++)tr.insert(node<T>{i,i,a[i]});
}
typename set<node<T>>::iterator split(int pos){
typename set<node<T>>::iterator it=tr.lower_bound(node<T>{pos,0,0});
if(it!=tr.end()&&(*it).l==pos)return it;
it--;
if((*it).r<pos)return tr.end();
int l=(*it).l,r=(*it).r;
T v=(*it).v;
return tr.erase(it),tr.insert(node<T>{l,pos-1,v}),tr.insert(node<T>{pos,r,v}).first;
}
void assign(int l,int r,T x){
typename set<node<T>>::iterator itr=split(r+1),itl=split(l);
tr.erase(itl,itr),tr.insert(node<T>{l,r,x});
}
void add(int l,int r,T x){
typename set<node<T>>::iterator itr=split(r+1),itl=split(l);
for(typename set<node<T>>::iterator it=itl;it!=itr;it++)(*it).v+=x;
}
};
01-Trie(正序建树)
template<int maxn,int maxd>struct __01trie{
int tr[maxn][2],cnt,vis[maxn];
void insert(int a,int pos=0){
for(int i=1<<maxd;i>0;i>>=1){
bool t=a&i;
if(!tr[pos][t])tr[pos][t]=++cnt;
pos=tr[pos][t],vis[pos]++;
}
}
void erase(int a,int pos=0){
for(int i=1<<maxd;i>0;i>>=1){
bool t=a&i;
pos=tr[pos][t],vis[pos]--;
}
}
int query(int a,int pos=0,int ans=0){
for(int i=1<<maxd;i>0;i>>=1){
bool t=a&i;
if(tr[pos][!t]&&vis[tr[pos][!t]])pos=tr[pos][!t],ans+=i;
else pos=tr[pos][t];
}
return ans;
}
};
01-Trie(倒序建树)
template<int maxn,int maxd>struct __01trie{
int tr[maxn][2],cnt,v[maxn];
bool w[maxn];
void pushup(int pos){
w[pos]=v[pos]=0;
if(tr[pos][0])w[pos]^=w[tr[pos][0]],v[pos]^=v[tr[pos][0]]<<1;
if(tr[pos][1])w[pos]^=w[tr[pos][1]],v[pos]^=(v[tr[pos][1]]<<1)|w[tr[pos][1]];
}
void insert(int a,int &pos,int d){
if(!pos)pos=++cnt;
if(d>maxd)w[pos]^=1;
else insert(a>>1,tr[pos][a&1],d+1),pushup(pos);
}
void erase(int a,int pos,int d){
if(d>maxd)w[pos]^=1;
else erase(a>>1,tr[pos][a&1],d+1),pushup(pos);
}
void add(int pos){
swap(tr[pos][0],tr[pos][1]);
if(tr[pos][0])add(tr[pos][0]);
pushup(pos);
}
};
Trie
template<int maxn1,int maxn2>struct trie{
int tr[maxn1][maxn2],cnt;
bool vis[maxn1];
int to_num(char c){
return c-'a';
}
void insert(string a,int pos=0){
for(int i=0;i<a.size();i++){
int t=to_num(a[i]);
if(!tr[pos][t])tr[pos][t]=++cnt;
pos=tr[pos][t];
}
vis[pos]=1;
}
bool query(string a,int pos=0){
for(int i=0;i<a.size();i++){
int t=to_num(a[i]);
if(!tr[pos][t])return 0;
pos=tr[pos][t];
}
return vis[pos];
}
};
zkw线段树
template<typename T,int maxn>struct zkw_SMT{
int num;
T v[maxn],tag[maxn];
void build(int n,T a[]){
for(num=1;num<=n+1;num<<=1);
for(int i=1;i<=n;i++)v[num+i]=a[i];
for(int i=num-1;i>=1;i--)v[i]=v[i<<1]+v[i<<1|1];
}
void add(int l,int r,T k,int cntl=0,int cntr=0,int len=1){
for(l=num+l-1,r=num+r+1;l^r^1;l>>=1,r>>=1,len<<=1){
v[l]+=cntl*k,v[r]+=cntr*k;
if(~l&1)v[l^1]+=len*k,tag[l^1]+=k,cntl+=len;
if(r&1)v[r^1]+=len*k,tag[r^1]+=k,cntr+=len;
}
for(;l;l>>=1,r>>=1)v[l]+=cntl*k,v[r]+=cntr*k;
}
T query(int l,int r,T ans=0,int cntl=0,int cntr=0,int len=1){
for(l=num+l-1,r=num+r+1;l^r^1;l>>=1,r>>=1,len<<=1){
ans+=cntl*tag[l]+cntr*tag[r];
if(~l&1)ans+=v[l^1],cntl+=len;
if(r&1)ans+=v[r^1],cntr+=len;
}
for(;l;l>>=1,r>>=1)ans+=cntl*tag[l]+cntr*tag[r];
return ans;
}
};
划分树
template<typename T,int maxn1,int maxn2>struct dividing_tree{
T tr[maxn1][maxn2],temp[maxn1];
int num,d,cnt[maxn1][maxn2];
void build(int n,T a[]){
for(num=1,d=0;num<n;num<<=1,d++);
for(int i=1;i<=n;i++)tr[i][0]=temp[i]=a[i];
sort(temp+1,temp+num+1);
for(int i=0,w=num;i<=d;i++,w>>=1){
for(int j=1;j<=num;j+=w){
T mid=temp[j+(w>>1)-1];
int r=w>>1;
for(int k=j;k<j+w;k++)if(tr[k][i]<mid)r--;
for(int k=j,lpos=j,rpos=j+(w>>1);k<j+w;k++){
if(k>j)cnt[k][i]=cnt[k-1][i];
if(tr[k][i]<mid||(tr[k][i]==mid&&r-->0))tr[lpos++][i+1]=tr[k][i],cnt[k][i]++;
else tr[rpos++][i+1]=tr[k][i];
}
}
}
}
T query(int l,int r,int k){
if(k<1||k>r-l+1)return -1;
for(int i=0,pos=1,l1,l2,r1,r2;i<=d;i++){
l1=(l==pos?0:cnt[l-1][i]),l2=cnt[r][i],r1=l-pos-l1,r2=r-pos-l2+1;
if(l2-l1>=k)l=pos+l1,r=pos+l2-1;
else pos+=(num>>(i+1)),l=pos+r1,r=pos+r2-1,k=k+l1-l2;
}
return tr[l][d];
}
};
有旋Treap
template<typename T,int maxn>struct treap{
T v[maxn];
int tr[maxn][2],num[maxn],sz[maxn],r[maxn],cnt;
void pushup(int pos){
sz[pos]=sz[tr[pos][0]]+sz[tr[pos][1]]+num[pos];
}
void rotate(int &pos,bool d){
int temp=tr[pos][!d];
tr[pos][!d]=tr[temp][d],tr[temp][d]=pos,pushup(pos),pushup(temp),pos=temp;
}
void insert(int &pos,T k){
if(!pos){
pos=++cnt,v[pos]=k,num[pos]=sz[pos]=1,r[pos]=rand();
return;
}
if(k==v[pos]){
num[pos]++,sz[pos]++;
return;
}
bool d=k>v[pos];
insert(tr[pos][d],k);
if(r[pos]<r[tr[pos][d]])rotate(pos,!d);
pushup(pos);
}
void erase(int &pos,T k){
if(!pos)return;
if(k==v[pos]){
if(!tr[pos][0]&&!tr[pos][1]){
num[pos]--,sz[pos]--;
if(!num[pos])pos=0;
}
else if(tr[pos][0]&&!tr[pos][1])rotate(pos,1),erase(tr[pos][1],k);
else if(!tr[pos][0]&&tr[pos][1])rotate(pos,0),erase(tr[pos][0],k);
else{
bool d=r[tr[pos][0]]>r[tr[pos][1]];
rotate(pos,d),erase(tr[pos][d],k);
}
}
else erase(tr[pos][k>v[pos]],k);
pushup(pos);
}
int rank(int pos,T k){
if(!pos)return 1;
if(k<v[pos])return rank(tr[pos][0],k);
else if(k==v[pos])return sz[tr[pos][0]]+1;
else return sz[tr[pos][0]]+num[pos]+rank(tr[pos][1],k);
}
T kth(int pos,int k){
if(!pos)return 0;
if(k<=sz[tr[pos][0]])return kth(tr[pos][0],k);
else if(k>sz[tr[pos][0]]+num[pos])return kth(tr[pos][1],k-sz[tr[pos][0]]-num[pos]);
else return v[pos];
}
T prev(int pos,T k){
if(!pos)return -inf;
if(k<=v[pos])return prev(tr[pos][0],k);
else return max(v[pos],prev(tr[pos][1],k));
}
T next(int pos,T k){
if(!pos)return inf;
if(k>=v[pos])return next(tr[pos][1],k);
else return min(v[pos],next(tr[pos][0],k));
}
};
Splay
template<typename T,int maxn>struct Splay{
T v[maxn];
int tr[maxn][2],num[maxn],sz[maxn],f[maxn],cnt;
bool get(int pos){
return tr[f[pos]][1]==pos;
}
void pushup(int pos){
sz[pos]=sz[tr[pos][0]]+sz[tr[pos][1]]+num[pos];
}
void rotate(int pos){
int f1=f[pos],f2=f[f1];
bool d=get(pos);
tr[f1][d]=tr[pos][d^1],f[tr[f1][d]]=f1,tr[f2][get(f1)]=pos,f[pos]=f2,tr[pos][d^1]=f1,f[f1]=pos,pushup(f1),pushup(pos);
}
void splay(int pos,int &rt){
for(int temp=f[rt];f[pos]!=temp;rotate(pos))if(f[f[pos]]!=temp)rotate(get(pos)==get(f[pos])?f[pos]:pos);
rt=pos;
}
int find(int pos,T k){
while(k!=v[pos])pos=tr[pos][k>v[pos]];
return pos;
}
void insert(int &rt,T k){
int pos=rt,p=0;
while(pos&&k!=v[pos])p=pos,pos=tr[pos][k>v[pos]];
if(pos)num[pos]++;
else{
pos=++cnt,v[pos]=k,f[pos]=p,num[pos]=sz[pos]=1;
if(p)tr[p][k>v[p]]=pos;
}
splay(pos,rt);
}
void erase(int &rt,T k){
splay(find(rt,k),rt);
if(num[rt]>1)num[rt]--,pushup(rt);
else{
if(!tr[rt][0]&&!tr[rt][1])rt=0;
else if(!tr[rt][0]&&tr[rt][1])rt=tr[rt][1],f[rt]=0;
else if(tr[rt][0]&&!tr[rt][1])rt=tr[rt][0],f[rt]=0;
else{
int pos=tr[rt][0];
while(tr[pos][1])pos=tr[pos][1];
splay(pos,tr[rt][0]),tr[pos][1]=tr[rt][1],f[tr[rt][1]]=pos,f[pos]=0,pushup(pos),rt=pos;
}
}
}
int rank(int &rt,T k){
return splay(find(rt,k),rt),sz[tr[rt][0]]+1;
}
T kth(int &rt,int k){
int pos=rt;
while(1){
if(k<=sz[tr[pos][0]])pos=tr[pos][0];
else{
k-=sz[tr[pos][0]]+num[pos];
if(k<=0)return splay(pos,rt),v[pos];
pos=tr[pos][1];
}
}
}
T prev(int &rt,T k,T ans=0){
insert(rt,k);
int pos=tr[rt][0];
while(tr[pos][1])pos=tr[pos][1];
return splay(pos,rt),ans=v[pos],erase(rt,k),ans;
}
T next(int &rt,T k,T ans=0){
insert(rt,k);
int pos=tr[rt][1];
while(tr[pos][0])pos=tr[pos][0];
return splay(pos,rt),ans=v[pos],erase(rt,k),ans;
}
};
Splay 区间翻转
template<typename T,int maxn>struct Splay{
T v[maxn];
int tr[maxn][2],sz[maxn],f[maxn],cnt;
bool tag[maxn];
bool get(int pos){
return tr[f[pos]][1]==pos;
}
void pushup(int pos){
sz[pos]=sz[tr[pos][0]]+sz[tr[pos][1]]+1;
}
void pushdown(int pos){
if(tag[pos])swap(tr[pos][0],tr[pos][1]),tag[tr[pos][0]]^=1,tag[tr[pos][1]]^=1,tag[pos]=0;
}
void rotate(int pos){
int f1=f[pos],f2=f[f1];
bool d=get(pos);
pushdown(f1),pushdown(pos),tr[f1][d]=tr[pos][d^1],f[tr[f1][d]]=f1,tr[f2][get(f1)]=pos,f[pos]=f2,tr[pos][d^1]=f1,f[f1]=pos,pushup(f1),pushup(pos);
}
void splay(int pos,int &rt){
for(int temp=f[rt];f[pos]!=temp;rotate(pos))if(f[f[pos]]!=temp)rotate(get(pos)==get(f[pos])?f[pos]:pos);
rt=pos;
}
void build(int &pos,int nl,int nr,int fa){
if(nl>nr)return;
int mid=(nl+nr)>>1;
pos=++cnt,v[pos]=mid,f[pos]=fa;
build(tr[pos][0],nl,mid-1,pos),build(tr[pos][1],mid+1,nr,pos),pushup(pos);
}
T kth(int &rt,int k){
int pos=rt;
while(1){
pushdown(pos);
if(k<=sz[tr[pos][0]])pos=tr[pos][0];
else{
k-=sz[tr[pos][0]]+1;
if(k<=0)return pos;
pos=tr[pos][1];
}
}
}
void reverse(int &rt,int l,int r){
splay(kth(rt,l-1),rt),splay(kth(rt,r+1),tr[rt][1]),tag[tr[tr[rt][1]][0]]^=1;
}
};
FHQ Treap
template<typename T,int maxn>struct FHQtreap{
T v[maxn];
int tr[maxn][2],sz[maxn],r[maxn],cnt;
void pushup(int pos){
sz[pos]=sz[tr[pos][0]]+sz[tr[pos][1]]+1;
}
void split1(int pos,T k,int &a,int &b){
if(!pos){
a=b=0;
return;
}
if(v[pos]<=k)a=pos,split1(tr[pos][1],k,tr[a][1],b);
else b=pos,split1(tr[pos][0],k,a,tr[b][0]);
pushup(pos);
}
void split2(int pos,int k,int &a,int &b){
if(!pos){
a=b=0;
return;
}
if(sz[tr[pos][0]]<k)a=pos,split2(tr[pos][1],k-sz[tr[pos][0]]-1,tr[a][1],b);
else b=pos,split2(tr[pos][0],k,a,tr[b][0]);
pushup(pos);
}
int merge(int a,int b){
if(!a||!b)return a^b;
if(r[a]<r[b])return tr[a][1]=merge(tr[a][1],b),pushup(a),a;
else return tr[b][0]=merge(a,tr[b][0]),pushup(b),b;
}
void insert(int &rt,T k,int a=0,int b=0){
split1(rt,k,a,b),v[++cnt]=k,sz[cnt]=1,r[cnt]=rand(),rt=merge(merge(a,cnt),b);
}
void erase(int &rt,T k,int a=0,int b=0,int c=0){
split1(rt,k-1,a,b),split1(b,k,b,c),rt=merge(merge(a,merge(tr[b][0],tr[b][1])),c);
}
int rank(int &rt,T k,int a=0,int b=0,int ans=0){
return split1(rt,k-1,a,b),ans=sz[a]+1,rt=merge(a,b),ans;
}
T kth(int &rt,int k,int a=0,int b=0,int c=0,int ans=0){
return split2(rt,k-1,a,b),split2(b,1,b,c),ans=v[b],rt=merge(merge(a,b),c),ans;
}
T prev(int &rt,T k,int a=0,int b=0,int c=0,int ans=0){
return split1(rt,k-1,a,c),split2(a,sz[a]-1,a,b),ans=v[b],rt=merge(merge(a,b),c),ans;
}
T next(int &rt,T k,int a=0,int b=0,int c=0,int ans=0){
return split1(rt,k,a,b),split2(b,1,b,c),ans=v[b],rt=merge(merge(a,b),c),ans;
}
};
FHQ Treap 区间翻转
template<typename T,int maxn>struct FHQtreap{
T v[maxn];
int tr[maxn][2],sz[maxn],r[maxn],cnt;
bool tag[maxn];
void pushup(int pos){
sz[pos]=sz[tr[pos][0]]+sz[tr[pos][1]]+1;
}
void pushdown(int pos){
if(tag[pos])swap(tr[pos][0],tr[pos][1]),tag[tr[pos][0]]^=1,tag[tr[pos][1]]^=1,tag[pos]=0;
}
void build(int &pos,int nl,int nr,int fa){
if(nl>nr)return;
int mid=(nl+nr)>>1;
pos=++cnt,v[pos]=mid,r[pos]=rand();
build(tr[pos][0],nl,mid-1,pos),build(tr[pos][1],mid+1,nr,pos),pushup(pos);
}
void split(int pos,int k,int &a,int &b){
if(!pos){
a=b=0;
return;
}
pushdown(pos);
if(sz[tr[pos][0]]<k)a=pos,split(tr[pos][1],k-sz[tr[pos][0]]-1,tr[a][1],b);
else b=pos,split(tr[pos][0],k,a,tr[b][0]);
pushup(pos);
}
int merge(int a,int b){
if(!a||!b)return a^b;
if(r[a]<r[b])return pushdown(a),tr[a][1]=merge(tr[a][1],b),pushup(a),a;
else return pushdown(b),tr[b][0]=merge(a,tr[b][0]),pushup(b),b;
}
T kth(int &rt,int k,int a=0,int b=0,int c=0,int ans=0){
return split(rt,k-1,a,b),split(b,1,b,c),ans=v[b],rt=merge(merge(a,b),c),ans;
}
void reverse(int &rt,int l,int r,int a=0,int b=0,int c=0){
split(rt,l-1,a,b),split(b,r-l+1,b,c),tag[b]^=1,rt=merge(merge(a,b),c);
}
};
配对堆
template<typename T>struct node{
T v;
int son,nxt;
};
template<typename T,int maxn>struct pairing_heap{
node<T>h[maxn];
int cnt;
T top(int rt){
return h[rt].v;
}
int merge(int a,int b){
if(!a||!b)return a^b;
if(h[a].v>h[b].v)swap(a,b);
return h[b].nxt=h[a].son,h[a].son=b,a;
}
void push(int &rt,T k){
h[++cnt].v=k,rt=merge(rt,cnt);
}
int merges(int pos){
if(!pos||!h[pos].nxt)return pos;
int x=h[pos].nxt,y=h[x].nxt;
return h[pos].nxt=h[x].nxt=0,merge(merges(y),merge(pos,x));
}
void pop(int &rt){
rt=merges(h[rt].son);
}
};
左偏树
template<typename T,int maxn>struct leftist_tree{
node<T>h[maxn];
int cnt;
T top(int rt){
return h[rt].v;
}
int merge(int a,int b){
if(!a||!b)return a^b;
if(h[a].v>h[b].v)swap(a,b);
h[a].rs=merge(h[a].rs,b);
if(h[h[a].ls].d<h[h[a].rs].d)swap(h[a].ls,h[a].rs);
return h[a].d=h[h[a].rs].d+1,a;
}
void push(int &rt,T k){
h[++cnt].v=k,rt=merge(rt,cnt);
}
void pop(int &rt){
rt=merge(h[rt].ls,h[rt].rs);
}
};