数据结构

分块

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);
  }
};
posted @ 2024-03-01 09:34  lgh_2009  阅读(15)  评论(0)    收藏  举报