Description
您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:
1. 插入x数
2. 删除x数(若有多个相同的数,因只删除一个)
3. 查询x数的排名(若有多个相同的数,因输出最小的排名)
4. 查询排名为x的数
5. 求x的前驱(前驱定义为小于x,且最大的数)
6. 求x的后继(后继定义为大于x,且最小的数)
Input
第一行为n,表示操作的个数,下面n行每行有两个数opt和x,opt表示操作的序号(1<=opt<=6)
Output
对于操作3,4,5,6每行输出一个数,表示对应答案
Sample Input
10
1 106465
4 1
1 317721
1 460929
1 644985
1 84185
1 89851
6 81968
1 492737
5 493598
Sample Output
106465
84185
492737
HINT
1.n的数据范围:n<=100000
2.每个数的数据范围:[-1e7,1e7]
Source
平衡树
Treap裸题,不得不说是一个很好的裸题。
在小绿的建议下用null替代了NULL
代码:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int SZ=10000010;
const int INF=2000000000;
struct node{
node *ch[2];
int r,sz,v,cnt;
void maintain();
int cmp(int x)
{
if(x==v) return -1;
return x < v? 0 : 1;
}
}T[SZ], *null, *root;
void node :: maintain()
{
sz=cnt + ch[0]->sz + ch[1]->sz;
}
int Tcnt=0;
node* newnode(int x)
{
node *k = T + (++ Tcnt);
k->ch[0] = k-> ch[1] = null; k->r=rand(); k->v=x; k->cnt=1; k->sz=k->cnt;
return k;
}
/*旋转*/
void rotate(node* &p,int d)
{
node *k=p->ch[d^1];
p->ch[d^1]=k->ch[d];
k->ch[d] = p;
p->maintain(); k->maintain();
p = k;
}
/*插入*/
void insert(node* &p,int x)
{
if(p==null)
{
p=newnode(x);
return ;
}
int d=p->cmp(x);
if(d==-1)
{
(p->cnt)++;
(p -> sz)++;
return ;
}
insert(p->ch[d],x);
if(p->ch[d]->r > p->r) rotate(p,d^1);
p->maintain();
}
/*删除*/
void erase(node* &p,int x)
{
if(p==null) return ;
int d=p->cmp(x);
if(d==-1)
{
if(p->cnt>1)
{
(p->cnt)--; (p->sz)--; return ;
}
if(p->ch[0]!=null && p->ch[1]!=null)
{
int dd = p->ch[0]->r > p->ch[1]->r ? 0 : 1;
rotate(p,dd^1);
erase(p->ch[dd^1],x);
}
else
{
if(p->ch[0]!=null) p=p->ch[0];
else p=p->ch[1];
}
}
else
erase(p->ch[d],x);
if(p!=null) p->maintain();
}
/*查询x的排名*/
int query_rank(node *p,int x)
{
if(p==null) return 0;
if(x==p->v)
return p -> ch[0] -> sz + 1;
else if(x < p->v)
return query_rank(p->ch[0],x);
else
return p -> cnt + p -> ch[0] -> sz + query_rank(p->ch[1],x);
}
/*查询第k小的数*/
int query_num(node *p,int k)
{
if(p == null) return 0;
int sz = p -> ch[0] -> sz;
if(k <= sz)
return query_num(p->ch[0],k);
else if(k > sz + p->cnt)
return query_num(p->ch[1],k - sz - p->cnt);
else
return p->v;
}
/*查询x的前驱*/
int query_pre(node *fuckdc,int x)
{
int ans = 0;
while(fuckdc != null)
{
if(fuckdc -> v >= x)
fuckdc = fuckdc -> ch[0];
else
{
ans = fuckdc -> v;
fuckdc = fuckdc -> ch[1];
}
}
return ans;
}
/*查询x的后继*/
int query_suf(node *fuckdc,int x)
{
int ans = 0;
while(fuckdc != null)
{
if(fuckdc -> v <= x)
fuckdc = fuckdc -> ch[1];
else
{
ans = fuckdc -> v;
fuckdc = fuckdc -> ch[0];
}
}
return ans;
}
int main()
{
freopen("phs.in","r",stdin);
freopen("phs.out","w",stdout);
null = newnode(-1000000000);
null -> sz = null -> cnt = 0;
null -> r = -1;
root = null;
int m;
scanf("%d",&m);
while(m--)
{
int opt,x;
scanf("%d%d",&opt,&x);
switch(opt)
{
case 1:
insert(root,x);
break;
case 2:
erase(root,x);
break;
case 3:
printf("%d\n",query_rank(root,x));
break;
case 4:
printf("%d\n",query_num(root,x));
break;
case 5:
printf("%d\n",query_pre(root,x));
break;
case 6:
printf("%d\n",query_suf(root,x));
break;
}
}
return 0;
}
/*
100
1 1
1 1
1 1
1 2
4 1
4 2
4 3
4 4
2 1
4 1
4 2
4 3
2 2
4 1
4 2
*/