它基本的支持一下操作:
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;
}