题目链接:https://vjudge.net/problem/HYSBZ-3224
转自:https://blog.csdn.net/qq_39897867/article/details/99719484
模板:https://blog.csdn.net/Roll_Keyboard/article/details/81045891
讲解:https://blog.csdn.net/yandaoqiusheng/article/details/85037548
#include <bits/stdc++.h>
using namespace std;
const int N = 100010;
struct Treap
{
int l,r; //左,右
int val,dat; //价值,随机值
int cnt,sz; //副本数,子树大小
} t[N];
int tot,root,n,INF = 0x7fffffff;
void init()
{
tot=0;
}
int New(int val)
{
t[++tot].val=val;
t[tot].dat=rand();
t[tot].l=t[tot].r=0;
t[tot].cnt=t[tot].sz=1;
return tot;
}
void update(int p)//统计子节点数
{
t[p].sz=t[t[p].l].sz+t[t[p].r].sz+t[p].cnt;
}
void build()
{
New(-INF);
New(INF);
root=1,t[1].r=2;
update(root);
}
void zig(int &p)//旋转操作
{
int q=t[p].l;
t[p].l=t[q].r,t[q].r=p,p=q;
update(t[p].r),update(p);
}
void zag(int &p)//旋转操作
{
int q=t[p].r;
t[p].r=t[q].l,t[q].l=p,p=q;
update(t[p].l),update(p);
}
void Insert(int &p,int val) //插入
{
if(p==0)//到达空节点
{
p=New(val);
return ;
}
if(val==t[p].val)
{
t[p].cnt++,update(p);
return ;
}
if(val<t[p].val)
{
Insert(t[p].l,val);
if(t[p].dat<t[t[p].l].dat)
zig(p);
}
else
{
Insert(t[p].r,val);
if(t[p].dat<t[t[p].r].dat)
zag(p);
}
update(p);
}
void Remove(int &p,int val) //删除
{
if(p==0)
return ;
if(val==t[p].val)
{
if(t[p].cnt>1)
{
t[p].cnt--,update(p);
return ;
}
if(t[p].l||t[p].r)
{
if(t[p].r==0||t[t[p].l].dat>t[t[p].r].dat)
zig(p),Remove(t[p].r,val);
else
zag(p),Remove(t[p].l,val);
update(p);
}
else
p=0;
return ;
}
val<t[p].val?Remove(t[p].l,val):Remove(t[p].r,val);
update(p);
}
int GetRankByVal(int p,int val) //排名(记得减1,因为有-inf)
{
if(p==0)
return 0;
if(val==t[p].val)
return t[t[p].l].sz+1;//注意这个地方
if(val<t[p].val)
return GetRankByVal(t[p].l,val);
return GetRankByVal(t[p].r,val)+t[t[p].l].sz+t[p].cnt;
}
int GetValByRank(int p,int rnk) //排名为rnk的数(rnk记得加1,因为有-inf)
{
if(p==0)
return INF;
if(t[t[p].l].sz>=rnk)
return GetValByRank(t[p].l,rnk);
if(t[t[p].l].sz+t[p].cnt>=rnk)
return t[p].val;
return GetValByRank(t[p].r,rnk-t[t[p].l].sz-t[p].cnt);
}
int GetPre(int val) //前驱 小于val的最大数
{
int ans=1;
int p=root;
while(p)
{
if(val==t[p].val)
{
if(t[p].l>0)
{
p=t[p].l;
while(t[p].r>0)
p=t[p].r;
ans=p;
}
break;
}
if(t[p].val<val&&t[p].val>t[ans].val)
ans=p;
p=val<t[p].val?t[p].l:t[p].r;
}
return t[ans].val;
}
int GetNext(int val) //后继
{
int ans=2;
int p=root;
while(p)
{
if(val==t[p].val)
{
if(t[p].r>0)
{
p=t[p].r;
while(t[p].l>0)
p=t[p].l;
ans=p;
}
break;
}
if(t[p].val>val&&t[p].val<t[ans].val)
ans=p;
p=val<t[p].val?t[p].l:t[p].r;
}
return t[ans].val;
}
int main()
{
int n;
scanf("%d",&n);
build();
for(int i=0; i<n; i++)
{
int a,b;
scanf("%d%d",&a,&b);
if(a==1)
{
Insert(root,b);
}
else if(a==2)
{
Remove(root,b);
}
else if(a==3)
{
printf("%d\n",GetRankByVal(root,b)-1);
}
else if(a==4)
{
printf("%d\n",GetValByRank(root,b+1));
}
else if(a==5)
{
printf("%d\n",GetPre(b));
}
else
{
printf("%d\n",GetNext(b));
}
}
return 0;
}