Treap,也叫做树堆,是指有一个随机附加域满足堆的性质的二叉搜索树。
如果一棵二叉搜索树插入节点的顺序是随机的,那我们得到的二叉搜索树在大多数情况下是平衡的,期望高度是log(n).
但有些情况下我们并不能得知所有待插入节点,打乱以后再插入,这时我们需要给二叉搜索树加上一个随机附加域,并使这个随机附加域(优先级)满足堆的性质,以此来实现“乱序插入”的想法,使二叉搜索树保持平衡。
Treap可以满足的序列操作:
1,插入一个数x
2,删除一个数x
3,查询x的排名
4,查询排名为x的数
5,查询x的前驱
6,查询x的后继
Treap的基本操作
1,newnode新建节点
2,split分裂 把Treap按照权值分割为两部分
3,merge合并 把Treap的两部分进行合并
4,insert插入 把Treap按照插入的权值Val分裂为两部分,然后merge左边和新点,再merge新的左边和右边
5,delete删除 把Treap分裂两次,中间那部分不管它,把两边merge一下
1 #include<cstdio> 2 #include<algorithm> 3 #include<ctime> 4 #define ls (a[u].l) 5 #define rs (a[u].r) 6 using namespace std; 7 const int maxn=200010; 8 int n,k,x,y,z,v,tot,root; 9 struct treap{int l,r,v,rnd,size;}a[maxn]; 10 void read(int &k){ 11 k=0; int f=1; char c=getchar(); 12 while(c<‘0‘||c>‘9‘)c==‘-‘&&(f=-1),c=getchar(); 13 while(‘0‘<=c&&c<=‘9‘)k=k*10+c-‘0‘,c=getchar(); 14 k*=f; 15 } 16 void newnode(int v){a[++tot]=(treap){0,0,v,rand()+1,1};} 17 void update(int u){a[u].size=a[ls].size+a[rs].size+1;} 18 void split(int u,int k,int &x,int &y){ 19 if(!k){x=0; y=u; return;} 20 if(a[u].size==k){x=u; y=0; return;} 21 if(a[ls].size>=k)split(a[u].l,k,x,a[u].l),y=u; 22 else split(a[u].r,k-a[ls].size-1,a[u].r,y),x=u; 23 update(u); 24 } 25 int merge(int x,int y){ 26 if(!(x*y)) return x+y; 27 if(a[x].rnd>a[y].rnd){ 28 a[y].l=merge(x,a[y].l); update(y); return y; 29 } 30 else{ 31 a[x].r=merge(a[x].r,y); update(x); return x; 32 } 33 } 34 int qrank(int u,int val){ 35 if(!u) return 0; 36 if(a[u].v>=val) return qrank(ls,val); 37 return qrank(rs,val)+a[ls].size+1; 38 } 39 int qval(int u,int k){ 40 if(a[ls].size+1==k) return a[u].v; 41 return a[ls].size>=k?qval(ls,k):qval(rs,k-a[ls].size-1); 42 } 43 int main(){ 44 srand(time(0)); root=tot=1; a[root].v=2e9; a[root].size=1; 45 read(n); 46 while(n--){ 47 read(k); read(v); 48 if(k==1){//插入 49 split(root,qrank(root,v),x,y); 50 newnode(v); root=merge(merge(x,tot),y); 51 } 52 if(k==2){//查询 53 split(root,qrank(root,v),x,y); 54 split(y,1,z,y); root=merge(x,y); 55 } 56 if(k==3) printf("%d\n",qrank(root,v)+1);//查询x的排名 57 if(k==4) printf("%d\n",qval(root,v));//查排名为x的数 58 if(k==5) printf("%d\n",qval(root,qrank(root,v)));//求x的前驱 59 if(k==6) printf("%d\n",qval(root,qrank(root,v+1)+1));//求x的后继 60 } 61 return 0; 62 } 63
洛谷3369
时间: 2024-11-09 08:06:40