Rt。调了一下发现大概是查询 x 的排名的函数挂掉了,有 hack 数据如下:
7
1 5
1 3
1 1
1 2
1 4
2 3
2 1
原本在第一个删除操作查询 3 的排名把 3 旋到树根后树的形态应该是这样:
3
/ \
2 4
/ \
1 5
但是实际上 3 的某一棵子树却消失了,也就是只能查询到左儿子或右儿子。
我怀疑大概是查询排名的函数的问题,但也有可能是其他地方的问题。求大佬帮忙康康/kel
//Think twice,code once.
#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
int n;
struct Splay
{
int tot,root;
int size[100005];
int son[100005][2];
int fa[100005];
int cnt[100005],val[100005];
int get(int x){return x==son[fa[x]][1];}
void update(int x){size[x]=size[son[x][0]]+size[son[x][1]]+cnt[x];return ;}
void clear(int x){size[x]=son[x][0]=son[x][1]=fa[x]=cnt[x]=val[x]=0;return ;}
void rotate(int x)
{
int y=fa[x],z=fa[fa[x]],chk=get(x);
son[y][chk]=son[x][chk^1];
if(son[x][chk^1]) fa[son[x][chk^1]]=y;
son[x][chk^1]=y;fa[y]=x;
fa[x]=z;
if(z) son[z][get(y)]=x;
update(y);
update(x);
return ;
}
void splay(int x)
{
for(int f=fa[x];f=fa[x],f;rotate(x))
if(fa[f]) rotate(get(x)==get(f)?f:x);
root=x;
return ;
}
void insert(int k)
{
if(!root)
{
son[tot][0]=son[tot][1]=fa[tot]=0;
root=++tot;
val[tot]=k;
size[tot]=cnt[tot]=1;
return ;
}
int x=root;
while(1)
{
if(val[x]==k)
{
cnt[x]++;
update(x);
update(fa[x]);
splay(x);
break;
}
int lst=x;
x=son[x][k>val[x]];
if(!x)
{
tot++;
son[tot][0]=son[tot][1]=0;
fa[tot]=lst;
son[lst][k>val[lst]]=tot;
val[tot]=k;
size[tot]=cnt[tot]=1;
update(fa[tot]);
splay(tot);
break;
}
}
return ;
}
int rank(int x)
{
int now=root,num=0;
while(1)
{
if(x<val[now]) now=son[now][0];
else
{
num+=size[son[now][0]];
if(x==val[now]) break;
num+=cnt[now];
now=son[now][1];
}
}
splay(now);
return num+1;
}
int pre(int x)
{
int now=root,ans=-1e9;
while(now)
{
if(x>val[now]) ans=max(ans,val[now]);
now=son[now][x>val[now]];
}
return ans;
}
int suf(int x)
{
int now=root,ans=1e9;
while(now)
{
if(x<val[now]) ans=min(ans,val[now]);
now=son[now][x>=val[now]];
}
return ans;
}
int kth(int k)
{
int now=root,num=0;
while(num<k)
if(num+size[son[now][0]]+cnt[now]<k) now=son[now][1],num+=son[now][0]+cnt[now];
else if(num+size[son[now][0]]<k&&num+size[son[now][0]]+cnt[now]>=k) break;
else now=son[now][0];
return val[now];
}
void dlt(int x)
{
rank(x);
if(cnt[root]>1){cnt[root]--;update(root);return ;}
if(!son[root][0]&&!son[root][1])
{
clear(root);
root=0;
return ;
}
if(!son[root][1])
{
int lst=root;
root=son[root][0];
fa[root]=0;
clear(lst);
return ;
}
if(!son[root][0])
{
int lst=root;
root=son[root][1];
fa[root]=0;
clear(lst);
return ;
}
int lst=root;
int now=son[root][0];
fa[now]=0;
root=now;
while(son[now][1]) now=son[now][1];
splay(now);
son[root][1]=son[lst][1];
update(root);
clear(lst);
return ;
}
}s;
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
int op,val;
scanf("%d%d",&op,&val);
switch(op)
{
case 1:s.insert(val);break;
case 2:s.dlt(val);break;
case 3:printf("%d\n",s.rank(val));break;
case 4:printf("%d\n",s.kth(val));break;
case 5:printf("%d\n",s.pre(val));break;
case 6:printf("%d\n",s.suf(val));break;
}
}
return 0;
}