[luogu 3369]普通平衡树(fhq_treap)

题目描述

您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:

  1. 插入x数

  2. 删除x数(若有多个相同的数,因只删除一个)

  3. 查询x数的排名(排名定义为比当前数小的数的个数+1。若有多个相同的数,因输出最小的排名)

  4. 查询排名为x的数

  5. 求x的前驱(前驱定义为小于x,且最大的数)

  6. 求x的后继(后继定义为大于x,且最小的数)

输入输出格式

输入格式:

第一行为n,表示操作的个数,下面n行每行有两个数opt和x,opt表示操作的序号( 1≤opt≤6 1 \leq opt \leq 6 1opt6 )

输出格式:

对于操作3,4,5,6每行输出一个数,表示对应答案

输入输出样例

输入样例#1: 复制
10
1 106465
4 1
1 317721
1 460929
1 644985
1 84185
1 89851
6 81968
1 492737
5 493598
输出样例#1: 复制
106465
84185
492737

说明

时空限制:1000ms,128M

1.n的数据范围: n≤100000 n \leq 100000 n100000

2.每个数的数据范围: $[-{10}^7, {10}^7]$

题解:

模板题,用的是fhq_treap。

 

 1 //Never forget why you start
 2 #include<iostream>
 3 #include<cstdio>
 4 #include<cstring>
 5 #include<cstdlib>
 6 #include<cmath>
 7 #include<algorithm>
 8 #include<ctime>
 9 #define ll(x) tre[x].child[0]
10 #define rr(x) tre[x].child[1]
11 #define son(x,t) tre[x].child[t]
12 using namespace std;
13 int n,m,cnt,root;
14 struct Treap{
15   int child[2],x,size,rev;
16 }tre[100005];
17 void push_up(int root){
18   tre[root].size=tre[ll(root)].size+tre[rr(root)].size+1;
19 }
20 int newnode(int x){
21   cnt++;
22   tre[cnt].size=1;
23   tre[cnt].rev=rand();
24   tre[cnt].x=x;
25   return cnt;
26 }
27 void split(int now,int k,int &x,int &y){
28   if(!now)x=y=0;
29   else{
30     if(tre[now].x<=k)
31       x=now,split(rr(now),k,rr(now),y);
32     else
33       y=now,split(ll(now),k,x,ll(now));
34     push_up(now);
35   }
36 }
37 int merge(int x,int y){
38   if(!x||!y)return x+y;
39   if(tre[x].rev<tre[y].rev){
40     rr(x)=merge(rr(x),y);
41     push_up(x);
42     return x;
43   }
44   else{
45     ll(y)=merge(x,ll(y));
46     push_up(y);
47     return y;
48   }
49 }
50 int find(int root,int k){
51   int y=tre[ll(root)].size;
52   if(y+1==k)return root;
53   else if(y>=k)return find(ll(root),k);
54   else find(rr(root),k-y-1);
55 }
56 int main(){
57   int i,j,a,b,c;
58   srand(time(0));
59   scanf("%d",&n);
60   while(n--){
61     scanf("%d%d",&i,&j);
62     if(i==1){
63       split(root,j,a,b);
64       root=merge(merge(a,newnode(j)),b);
65     }
66     if(i==2){
67       split(root,j,a,c);
68       split(a,j-1,a,b);
69       b=merge(ll(b),rr(b));
70       root=merge(merge(a,b),c);
71     }
72     if(i==3){
73       split(root,j-1,a,b);
74       printf("%d\n",tre[a].size+1);
75       root=merge(a,b);
76     }
77     if(i==4){
78       printf("%d\n",tre[find(root,j)].x);
79     }
80     if(i==5){
81       split(root,j-1,a,b);
82       printf("%d\n",tre[find(a,tre[a].size)].x);
83       root=merge(a,b);
84     }
85     if(i==6){
86       split(root,j,a,b);
87       printf("%d\n",tre[find(b,1)].x);
88       root=merge(a,b);
89     }
90   }
91   return 0;
92 }

 

 

 

 

posted @ 2018-01-13 11:10  kakakakakaka  阅读(276)  评论(0编辑  收藏  举报

Never forget why you start

//鼠标爆炸特效