Treap--简单的平衡二叉搜索树

它基本的支持一下操作:
1. 插入x数
2. 删除x数(若有多个相同的数,只删除一个)
3. 查询x数的排名(若有多个相同的数,输出最小的排名)
4. 查询排名为x的数
5. 求x的前驱(前驱定义为小于x,且最大的数)
6. 求x的后继(后继定义为大于x,且最小的数)
模板如下:

#include<cstdio>
#include<cstdlib>//有rand()[随机函数]
#include<iostream>
using namespace std;
struct treap
{
    int l,r,size,recy,v,rnd;
}t[1000010];
int tot,m,root,ans;
inline void update(int k)
{
    t[k].size=t[t[k].l].size+t[t[k].r].size+  t[k].recy;
}
//&k:节点编号 
inline void ll(int &k)
{
    int y=t[k].r;t[k].r=t[y].l;t[y].l=k;
    t[y].size=t[k].size;update(k);k=y;
}
inline void rr(int &k)
{
    int y=t[k].l;t[k].l=t[y].r;t[y].r=k;
    t[y].size=t[k].size;update(k);k=y;
}
void insert(int &k,int num)
{
    if(k==0)
    {
        ++tot;k=tot;t[k].size=t[k].recy=1;
        t[k].v=num;   t[k].rnd=rand();
        return ;
    }
    ++t[k].size;
    if(t[k].v==num) ++t[k].recy;
    else if(t[k].v<num)
    {
        insert(t[k].r,num);
        if(t[t[k].r].rnd<t[k].rnd) ll(k);
    }
    else
    {
        insert(t[k].l,num);
        if(t[t[k].l].rnd<t[k].rnd) rr(k);
    }
}
void delet(int &k,int num)
{
    if(k==0) return ;
    if(t[k].v==num)
    {
        if(t[k].recy>1) 
        {
            --t[k].recy;--t[k].size;
            return;
        }
        if(t[k].l*t[k].r==0) k=t[k].l+t[k].r;
        else if(t[t[k].l].rnd<t[t[k].r].rnd) rr(k),delet(k,num);
        else ll(k),delet(k,num);
    }
    else if(num>t[k].v) --t[k].size,delet(t[k].r,num);
    else --t[k].size,delet(t[k].l,num);
}
int atrank(int k,int num)//寻找值为num的数的排名
{
    if(k==0) return 0;
    if(t[k].v==num) return t[t[k].l].size+1;
    else if(num>t[k].v) return t[t[k].l].size+t[k].recy+atrank(t[k].r,num);
    else return atrank(t[k].l,num);
}
int rerank(int k,int num)//寻找排名为num的数值 
{
    if(k==0) return 0;
    if(num<=t[t[k].l].size) return rerank(t[k].l,num);
    else if(num>t[t[k].l].size+t[k].recy) return rerank(t[k].r,num-t[t[k].l].size-t[k].recy);
    else return t[k].v;
}
void pre(int k,int num)//找前驱 
{
    if(k==0) return;
    if(num>t[k].v) 
    {
        ans=k;pre(t[k].r,num);
    }
    else pre(t[k].l,num);
}
void suc(int k,int num)//找后继 
{
    if(k==0) return ;
    if(num<t[k].v)
    {
        ans=k;suc(t[k].l,num);
    }
    else suc(t[k].r,num);
}
int main()
{
    int f,x;
    scanf("%d",&m);
    while(m--)
    {
        scanf("%d%d",&f,&x);
        ans=0;
        if(f==1) insert(root,x);
        if(f==2) delet(root,x);
        if(f==3) printf("%d\n",atrank(root,x));
        if(f==4) printf("%d\n",rerank(root,x));
        if(f==5) {pre(root,x);printf("%d\n",t[ans].v);}
        if(f==6) {suc(root,x);printf("%d\n",t[ans].v);}
    }
    return 0;
}

来道题:
bzoj1503 [NOI2004]郁闷的出纳员

#include<iostream>
#include<cstdio>
#include<cstdlib>
using namespace std;
const int maxn=100020;
int s[maxn],l[maxn],r[maxn],v[maxn],tot=0,rnd[maxn],n,m,pre,root,ans; 
inline void pushup(int k)
{s[k]=s[l[k]]+s[r[k]]+1;}
inline void rturn(int &k)
{int t=l[k];l[k]=r[t];r[t]=k;s[t]=s[k];pushup(k);k=t;}
inline void lturn(int &k)
{int t=r[k];r[k]=l[t];l[t]=k;s[t]=s[k];pushup(k);k=t;}
void ins(int &k,int num)
{
    if(!k)
    {k=++tot;v[k]=num;s[k]=1;l[k]=r[k]=0;rnd[k]=rand();return;}
  s[k]++;
  if(num<v[k])
  {ins(l[k],num);if(rnd[l[k]]<rnd[k])rturn(k);}
  else
    {ins(r[k],num);if(rnd[r[k]]<rnd[k])lturn(k);}  
}
int del(int &k,int num){
    if(k==0)return 0;
    if(v[k]<num){
      int t=s[l[k]]+1;k=r[k];return t+del(k,num);
  }else{
    int t=del(l[k],num);s[k]-=t;return t;
    }
}
int find(int k,int x){
    if(s[l[k]]+1==x)return v[k]+pre;
    else if(s[l[k]]+1<x)return find(r[k],x-s[l[k]]-1);
    else return find(l[k],x);
}
int main(){
    srand(1);
    scanf("%d%d",&n,&m);
    char ch[1];int x;
    while(n--){
        scanf("%s%d",ch,&x);
        if(ch[0]=='I')if(x>=m)ins(root,x-pre);
        if(ch[0]=='A')pre+=x;
        if(ch[0]=='S'){
            pre-=x;ans+=del(root,m-pre);
      }
      if(ch[0]=='F'){
        if(x>s[root])printf("-1\n");
        else printf("%d\n",find(root,s[root]-x+1));
      }
  }
  printf("%d\n",ans);
  return 0;
}

以及poj2892‘’鬼子进村‘’(我同桌这样叫的)

#include<cstdio>
#include<cstdlib>
//#include<ctime>
using namespace std;
int tot=0,n,m,root,l,r,last[60000],pop=0;
struct treap
{
    int size,l,r,rnd,v,recy;
}t[60000];
inline void update(int k)
{
    t[k].size=t[t[k].l].size+t[t[k].r].size+t[k].recy;
}
inline void ll(int &k)
{
    int y=t[k].r;t[k].r=t[y].l;t[y].l=k;
    t[y].size=t[k].size;update(k);k=y;
} 
inline void rr(int &k)
{
    int y=t[k].l;t[k].l=t[y].r;t[y].r=k;
    t[y].size=t[k].size;update(k);k=y;
}
void insert(int &k,int num)
{
    if(k==0)
    {
        tot++;k=tot;t[k].size=t[k].recy=1;t[k].v=num;t[k].rnd=rand();
        return;
    }
    t[k].size++;
    if(num==t[k].v) t[k].recy++;
    else if(num<t[k].v)
    {
        insert(t[k].l,num);
        if(t[k].rnd>t[t[k].l].rnd) rr(k);
    }
    else
    {
        insert(t[k].r,num);
        if(t[k].rnd>t[t[k].r].rnd) ll(k);
    }
}
void delet(int &k,int num)
{
    if(k==0) return;
    if(num==t[k].v)
    {
        if(t[k].recy>1) 
        {
            t[k].recy--;t[k].size--;
            return;
        }
        else if(t[k].l*t[k].r==0) k=t[k].l+t[k].r;
        else
        {
            if(t[t[k].l].rnd<t[t[k].r].rnd)
            {
                rr(k);delet(k,num);
            }
            else
            {
                ll(k);delet(k,num);
            }
        }
    }
    else if(num<t[k].v) --t[k].size,delet(t[k].l,num);
    else --t[k].size,delet(t[k].r,num);
}
void find(int k,int num)
{
    if(k==0) return;
    if(num<=t[k].v&&r>=t[k].v) r=t[k].v;//=
    if(num>=t[k].v&&l<=t[k].v) l=t[k].v;
    if(num>t[k].v) find(t[k].r,num);
    else if(num<t[k].v) find(t[k].l,num);
}
void init()
{
    char c[2];int x;
    scanf("%d%d",&n,&m);
    while(m--)
    {
        scanf("%s",c);
        if(c[0]=='D')
        {
            scanf("%d",&x);
            insert(root,x);
            last[++pop]=x;
        }
        if(c[0]=='R')
        {
            delet(root,last[pop]);pop--;
        }
        if(c[0]=='Q')
        {
            scanf("%d",&x);
            l=0;r=n+1;
            find(root,x);
            if(l==x&r==x) printf("0\n");
            else printf("%d\n",r-l-1);
        }
    }
}
int main()
{
    //srand(1);
    init();
    return 0;
}
    原文作者:平衡二叉树
    原文地址: https://blog.csdn.net/zxw0819/article/details/73477391
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞