LOJ104 普通平衡树

题目描述

这是一道模板题。

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

  1. 插入  x 数;
  2. 删除  x 数(若有多个相同的数,因只删除一个);
  3. 查询  x 数的排名(若有多个相同的数,因输出最小的排名);
  4. 查询排名为 x 的数;
  5. 求 x 的前趋(前趋定义为小于 x,且最大的数);
  6. 求 x 的后继(后继定义为大于 x,且最小的数)。

输入格式

第一行为 n,表示操作的个数,下面 n 行每行有两个数 opt 和 x 表示操作的序号(1<=opt<=6)。

输出格式

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

样例

样例输入

10
1 106465
4 1
1 317721
1 460929
1 644985
1 84185
1 89851
6 81968
1 492737
5 493598

样例输出

106465
84185
492737

数据范围与提示

 1<=n<=105,-107<=x<=107
 ___________________________________________________________________________
 
fhq_treap模板
___________________________________________________________________________
  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 const int maxn=1e5+10;
  4 struct node
  5 {
  6     int val,lc,rc,siz,rd;
  7 }tr[maxn];
  8 int cnt,root,n;
  9 int newnode(int v)
 10 {
 11     ++cnt;
 12     tr[cnt].val=v;
 13     tr[cnt].siz=1;
 14     tr[cnt].rd=rand();
 15     tr[cnt].lc=tr[cnt].rc=0;
 16     return cnt;
 17 }
 18 void update(int cur)
 19 {
 20     tr[cur].siz=tr[tr[cur].lc].siz+tr[tr[cur].rc].siz+1;
 21 }
 22 int merge(int x,int y)
 23 {
 24     if(x*y==0)return x+y;
 25     if(tr[x].rd<tr[y].rd)
 26     {
 27         tr[x].rc=merge(tr[x].rc,y);
 28         update(x);
 29         return x;
 30     }
 31     else
 32     {
 33         tr[y].lc=merge(x,tr[y].lc);
 34         update(y);
 35         return y;
 36     }
 37 }
 38 void split(int cur,int v,int &x,int &y)
 39 {
 40     if(!cur)x=y=0;
 41     else
 42     {
 43         if(tr[tr[cur].lc].siz+1<=v)
 44         {
 45             x=cur;
 46             split(tr[cur].rc,v-tr[tr[cur].lc].siz-1,tr[cur].rc,y);
 47             update(cur);
 48         }
 49         else
 50         {
 51             y=cur;
 52             split(tr[cur].lc,v,x,tr[cur].lc);
 53             update(cur);
 54         }
 55     }
 56 }
 57 void splitv(int cur,int v,int &x,int &y)
 58 {
 59     if(!cur)x=y=0;
 60     else
 61     {
 62         if(tr[cur].val<=v)
 63         {
 64             x=cur;
 65             splitv(tr[cur].rc,v,tr[cur].rc,y);
 66             update(cur);
 67         }
 68         else
 69         {
 70             y=cur;
 71             splitv(tr[cur].lc,v,x,tr[cur].lc);
 72             update(cur);
 73         }
 74     }
 75 }
 76 void insert(int v)
 77 {
 78     int x,y;
 79     splitv(root,v,x,y);
 80     root=merge(merge(x,newnode(v)),y);
 81 }
 82 void del(int v)
 83 {
 84     int x,y,z;
 85     splitv(root,v,x,z);
 86     splitv(x,v-1,x,y);
 87     y=merge(tr[y].lc,tr[y].rc);
 88     root=merge(merge(x,y),z);
 89 }
 90 void find(int v)
 91 {
 92     int x,y;
 93     splitv(root, v-1,x,y);
 94     printf("%d\n",tr[x].siz+1);
 95     root=merge(x,y);
 96 }
 97 void kth(int now,int v)
 98 {
 99     int cur=now;
100     if(v>tr[now].siz || v<1)return ;
101     while(cur)
102     {
103         if(tr[tr[cur].lc].siz+1==v)
104         {
105             printf("%d\n",tr[cur].val);
106             return ;
107         }
108         else if(tr[tr[cur].lc].siz >= v)cur=tr[cur].lc;
109         else
110         {
111             v-=tr[tr[cur].lc].siz+1;
112             cur=tr[cur].rc;
113         }
114     }
115 }
116 void pre(int v)
117 {
118     int x,y,z;
119     splitv(root,v-1,x,y);
120     kth(x,tr[x].siz);
121     root=merge(x,y);
122 }
123 void next(int v)
124 {
125     int x,y,z;
126     splitv(root,v,x,y);
127     kth(y,1);
128     root=merge(x,y);
129 }
130 int main()
131 {
132     scanf("%d",&n);
133     for(int op,x,i=0;i<n;++i)
134     {
135         scanf("%d%d",&op,&x);
136         if(op==1)insert(x);
137         else if(op==2)del(x);
138         else if(op==3)find(x);
139         else if(op==4)kth(root,x);
140         else if(op==5)pre(x);
141         else next(x);
142     }
143     return 0;
144 }
View Code

 

posted on 2019-04-10 16:02  gryzy  阅读(183)  评论(0编辑  收藏  举报

导航