luogu p3369

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

插入x数
删除x数(若有多个相同的数,因只删除一个)
查询x数的排名(排名定义为比当前数小的数的个数+1。若有多个相同的数,因输出最小的排名)
查询排名为x的数
求x的前驱(前驱定义为小于x,且最大的数)
求x的后继(后继定义为大于x,且最小的数)
输入输出格式
输入格式:
第一行为n,表示操作的个数,下面n行每行有两个数opt和x,opt表示操作的序号( 1≤opt≤6 )

输出格式:
对于操作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
2.每个数的数据范围: [-{10}^7, {10}^7]

--------------------------------------------------------------------------------------

刚学的,不用旋转的TREAP

好写,主要就是split和merge两个操作。

可以实现可持久化。

可以实现区间操作。

据说,比splay要慢

--------------------------------------------------------------------------------------

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 const int maxn=1e5+5;
  4 const int inf=1e9;
  5 struct node
  6 {
  7     int ch[2],val,rd,siz;
  8 }tr[maxn];
  9 int n,m,l,r;
 10 int tot,root;
 11 int newnode(int v)
 12 {
 13     ++tot;
 14     tr[tot].val=v;
 15     tr[tot].rd=rand();
 16     tr[tot].siz=1;
 17     tr[tot].ch[0]=tr[tot].ch[1]=0;
 18     return tot;
 19 }
 20 void update(int x)
 21 {
 22     tr[x].siz=tr[tr[x].ch[0]].siz+tr[tr[x].ch[1]].siz+1;
 23 }
 24 int merge(int a,int b)
 25 {
 26     if(a*b==0)return a+b;
 27     if(tr[a].rd<tr[b].rd)
 28     {
 29         tr[a].ch[1]=merge(tr[a].ch[1],b);
 30         update(a);
 31         return a;
 32     }
 33     else 
 34     {
 35         tr[b].ch[0]=merge(a,tr[b].ch[0]);
 36         update(b);
 37         return b;
 38     }
 39 }
 40 void split(int cur,int k,int &x,int &y)
 41 {
 42     if(!cur)x=y=0;
 43     else
 44     {
 45         if(tr[cur].val<=k)
 46         {
 47             x=cur;
 48             split(tr[cur].ch[1],k,tr[cur].ch[1],y);
 49         }
 50         else
 51         {
 52             y=cur;
 53             split(tr[cur].ch[0],k,x,tr[cur].ch[0]);
 54         }
 55         update(cur);
 56     }
 57 }
 58 void insert(int v)
 59 {
 60     int x,y;
 61     split(root,v,x,y);
 62     root=merge(merge(x,newnode(v)),y);
 63 }
 64 void del(int v)
 65 {
 66     int x,y,z;
 67     split(root,v,x,z);
 68     split(x,v-1,x,y);
 69     y=merge(tr[y].ch[0],tr[y].ch[1]);
 70     root=merge(merge(x,y),z);
 71 }
 72 void findrank(int v)
 73 {
 74     int x,y;
 75     split(root,v-1,x,y);
 76     printf("%d
",tr[x].siz+1);
 77     root=merge(x,y);
 78 }
 79 int kth(int now,int k)
 80 {
 81     int cur=now;
 82     while(cur)
 83     {
 84         if(tr[tr[cur].ch[0]].siz+1==k)return tr[cur].val;
 85         else if(tr[tr[cur].ch[0]].siz>=k)cur=tr[cur].ch[0];
 86         else 
 87         {
 88             k-=tr[tr[cur].ch[0]].siz+1;
 89             cur=tr[cur].ch[1];
 90         }
 91     }
 92     return -inf;
 93 }
 94 void pre(int v)
 95 {
 96     int x,y;
 97     split(root,v-1,x,y);
 98     printf("%d
",kth(x,tr[x].siz));
 99     root=merge(x,y);
100 }
101 void suc(int v)
102 {
103     int x,y;
104     split(root,v,x,y);
105     printf("%d
",kth(y,1));
106     root=merge(x,y);
107 }
108 int main()
109 {
110     srand((unsigned)time(NULL));
111     int n,op,v;
112     scanf("%d",&n);
113     while(n--)
114     {
115         scanf("%d%d",&op,&v);
116         switch(op)
117         {
118             case 1:insert(v);break;
119             case 2:del(v);break;
120             case 3:findrank(v);break;
121             case 4:printf("%d
",kth(root,v));break;
122             case 5:pre(v);break;
123             case 6:suc(v);break;
124             default:break;
125         }
126     }    
127     return 0;
128 }
View Code
原文地址:https://www.cnblogs.com/gryzy/p/10613064.html