rt ,对着书和同学老师的 AC 代码找了好几遍,没找出问题所在。评测记录,求助神犇。
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+5,inf=1e9+114514;
//treap: 这棵树需要同时满足大根堆和二叉搜索树的性质
mt19937 rnd(0);//随机数
struct node{
int l,r;
int val,dat;
int cnt,size;
} tr[maxn];
int root,tot;
int newnode(int val){
tr[++tot].val=val,tr[tot].dat=rnd();
tr[tot].cnt=tr[tot].size=1;
return tot;
}
inline void pushup(int p){
tr[p].size=tr[tr[p].l].size+tr[tr[p].r].size+tr[p].cnt;
}
void zig(int &p){
//将 p 点的左子树绕 p 顺时针旋转为 p 的父节点
int q=tr[p].l;
tr[p].l=tr[q].r,tr[q].r=p;
p=q;
pushup(tr[p].r),pushup(p);
}
void zag(int &p){
//将 p 点的右子树绕 p 逆时针旋转为 p 的父节点
int q=tr[p].r;
tr[p].r=tr[q].l,tr[q].l=p;
p=q;
pushup(tr[p].l),pushup(p);
}
void build(){
newnode(-inf),newnode(inf);
tr[1].r=2,root=1;
if(tr[2].dat>tr[1].dat) swap(tr[1].dat,tr[2].dat);
}
int getrank(int p,int val){
if(p==0) return 1;
if(val==tr[p].val) return tr[tr[p].l].size+1;
if(val<tr[p].val) return getrank(tr[p].l,val);
return tr[tr[p].l].size+tr[p].cnt+getrank(tr[p].r,val);
}
int getval(int p,int Rank){
if(p==0) return inf;
if(tr[tr[p].l].size>=Rank) return getval(tr[p].l,Rank);
if(tr[tr[p].l].size+tr[p].cnt>=Rank) return tr[p].val;
return getval(tr[p].r,Rank-tr[tr[p].l].size-tr[p].cnt);
}
void insert(int &p,int val){
if(p==0){
p=newnode(val);
return;
}
if(tr[p].val==val) tr[p].cnt++;
else if(val<tr[p].val){
insert(tr[p].l,val);
if(tr[tr[p].l].dat>tr[p].dat) zig(p);
} else {
insert(tr[p].r,val);
if(tr[tr[p].r].dat>tr[p].dat) zag(p);
}
pushup(p);
}
void remove(int &p,int val){
if(p==0) return;
if(tr[p].val==val){
if(tr[p].cnt>1){
tr[p].cnt--,pushup(p);
return;
}
if(tr[p].l||tr[p].r){
if(tr[p].r==0||tr[tr[p].l].dat>tr[tr[p].r].dat) zig(p),remove(tr[p].r,val);
else zag(p),remove(tr[p].l,val);
pushup(p);
} else p=0;
return;
}
if(val<tr[p].val) remove(tr[p].l,val);
else remove(tr[p].r,val);
pushup(p);
}
int pre(int val){
int ans=1,p=root;
while(p){
if(tr[p].val==val){
if(tr[p].l>0){
p=tr[p].l;
while(tr[p].r>0) p=tr[p].r;
ans=p;
}
break;
}
if(tr[p].val<val&&tr[p].val>tr[ans].val) ans=p;
p=val<tr[p].val?tr[p].l:tr[p].r;
}
return tr[ans].val;
}
int nxt(int val){
int ans=2,p=root;
while(p){
if(tr[p].val==val){
if(tr[p].r>0){
p=tr[p].r;
while(tr[p].l>0) p=tr[p].l;
ans=p;
}
break;
}
if(tr[p].val>val&&tr[p].val<tr[ans].val) ans=p;
p=val<tr[p].val?tr[p].l:tr[p].r;
}
return tr[ans].val;
}
int main(){
int n;
scanf("%d",&n);
build();
int op,x;
while(n--){
scanf("%d %d",&op,&x);
if(op==1) insert(root,x);
else if(op==2) remove(root,x);
else if(op==3) printf("%d\n",getrank(root,x)-1);
else if(op==4) printf("%d\n",getval(root,x+1));
else if(op==5) printf("%d\n",pre(x));
else printf("%d\n",nxt(x));
}
return 0;
}