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]
真正意义上第一道手写的SPLAY,还是出了很多BUG
注意题目找前驱后驱那些数不一定被插入了序列中,所以需先插入再查找,简直坑到爆,调了半天才发现题理解错了
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
const int maxn=1e5+5,INF=0x7f7f7f7f;
int n,maxnode,root;
queue<int>que;
struct Node
{
int val,size,cnt,fa,ch[2];
}node[maxn];
#define val(x) node[x].val
#define size(x) node[x].size
#define cnt(x) node[x].cnt
#define ch(x,d) node[x].ch[d]
#define fa(x) node[x].fa
void recycle(int x)
{
que.push(x);
}
int require()
{
int ret;
if (!que.empty()) ret=que.front(),que.pop();
else ret=++maxnode;
return ret;
}
void update(int x)
{
size(x)=cnt(x);
int L=ch(x,0),R=ch(x,1);
if (L) size(x)+=size(L);
if (R) size(x)+=size(R);
}
void rotate(int x,int &rt)
{
int y=fa(x),z=fa(y),L=ch(y,1)==x,R=L^1;
if (y==rt) rt=x;
else ch(z,ch(z,1)==y)=x;
fa(ch(x,R))=y; fa(y)=x; fa(x)=z; ch(y,L)=ch(x,R); ch(x,R)=y;
update(y); update(x);
}
void splay(int x,int &rt)
{
while (x^rt)
{
int y=fa(x),z=fa(y);
if (y^rt)
if ((x==ch(y,0)^(y==ch(z,0)))) rotate(x,rt);
else rotate(y,rt);
rotate(x,root);
}
}
void insert(int key)
{
if (!root) {root=require();val(root)=key;cnt(root)=size(root)=1;return;}
int x=root,y=0;
while (x&&(key^val(x))) y=x,x=ch(x,key>val(x));
if (x) cnt(x)++;
else x=require(),val(x)=key,cnt(x)=size(x)=1,ch(y,key>val(y))=x,fa(x)=y;
splay(x,root);
}
int find(int key)
{
int x=root;
while (key^val(x)) x=ch(x,key>val(x));
return x;
}
int pre(int x)
{
splay(x,root);
x=ch(x,0);
while (ch(x,1)) x=ch(x,1);
return x;
}
int nxt(int x)
{
splay(x,root);
x=ch(x,1);
while (ch(x,0)) x=ch(x,0);
return x;
}
void erase(int key)
{
int x=find(key);
splay(x,root);
cnt(x)--;
if (cnt(x)) return ;
int L=pre(x),R=nxt(x);
splay(L,root); splay(R,ch(L,1));
ch(R,0)=0; recycle(x);
update(R); update(L);
}
int rank(int x)
{
splay(x,root);
return size(ch(x,0))+1;
}
int query(int x,int rk)
{
int Lsize=size(ch(x,0));
if (rk<=Lsize) return query(ch(x,0),rk);
if (rk<=Lsize+cnt(x)) return val(x);
return query(ch(x,1),rk-Lsize-cnt(x));
}
int Pre(int key)
{
insert(key);
int rt=pre(root);
erase(key);
return rt;
}
int Nxt(int key)
{
insert(key);
int rt=nxt(root);
erase(key);
return rt;
}
int main()
{
// freopen("splay.in","r",stdin);
scanf("%d",&n);
insert(INF); insert(-INF);
while (n--)
{
int op,x;
scanf("%d%d",&op,&x);
switch (op)
{
case 1:insert(x);break;
case 2:erase(x);break;
case 3:printf("%d\n",rank(find(x))-1);break;
case 4:printf("%d\n",query(root,x+1));break;
case 5:printf("%d\n",val(Pre(x)));break;
case 6:printf("%d\n",val(Nxt(x)));break;
}
}
return 0;
}