splay
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int v[100010],fa[100010],ch[100010][2],sz[100010],tot[100010],rt,n,op,x,cnt,pred,succ;
char c;
inline void GET(int &n)
{
int f=1;n=0;
do{c=getchar();if(c=='-')f=-1;}while(c>'9'||c<'0');
while(c<='9'&&c>='0'){n=n*10+c-'0';c=getchar();}
n*=f;
}
inline void pushup(int x)
{
sz[x]=sz[ch[x][0]]+sz[ch[x][1]]+tot[x];
}
inline void rotate(int x)
{
int y=fa[x],z=fa[y];
bool flag=(ch[y][1]==x);
ch[y][flag]=ch[x][!flag];
fa[ch[y][flag]]=y;
ch[x][!flag]=y;
fa[ch[x][!flag]]=x;
fa[x]=z;
ch[z][y==ch[z][1]]=x;
pushup(x);
pushup(y);
}
inline void splay(int x,int goal)
{
for(int y;(y=fa[x])!=goal;rotate(x))
{
int z=fa[y];
if(fa[y]!=goal)
{
if((ch[z][0]==y)^(ch[y][0]==x))rotate(x);
else rotate(y);
}
}
if(!goal)rt=x;
pushup(x);
}
inline void insert(int val)
{
int x=rt,y=0;
while(x)
{
if(v[x]==val){++tot[x];splay(x,0);return;}
y=x;
x=ch[x][val>v[x]];
}
x=++cnt;
v[x]=val;
sz[x]=tot[x]=1;
fa[x]=y;
ch[y][v[x]>v[y]]=x;
splay(x,0);
}
int kth(int r,int x)
{
if(x>=sz[ch[r][0]]+1&&x<=sz[ch[r][0]]+tot[r])return v[r];
if(x<sz[ch[r][0]]+1)return kth(ch[r][0],x);
return kth(ch[r][1],x-sz[ch[r][0]]-tot[r]);
}
int rnk(int r,int x)
{
if(x==v[r])return sz[ch[r][0]]+1;
if(x<v[r])return rnk(ch[r][0],x);
return rnk(ch[r][1],x)+sz[ch[r][0]]+tot[r];
}
void predecessor(int r,int x)
{
if(0==r)return;
if(x>v[r])
{
pred=r;
predecessor(ch[r][1],x);
}
else predecessor(ch[r][0],x);
}
void successor(int r,int x)
{
if(0==r)return;
if(x<v[r])
{
succ=r;
successor(ch[r][0],x);
}
else successor(ch[r][1],x);
}
void del(int val)
{
successor(rt,val);
predecessor(rt,val);
splay(pred,0);
splay(succ,pred);
if(tot[ch[succ][0]]>1)
{
--tot[ch[succ][0]];
splay(ch[succ][0],0);
}
else
{
ch[succ][0]=0;
splay(succ,0);
}
}
int main()
{
GET(n);
insert(999999999);
insert(-999999999);
while(n--)
{
GET(op);GET(x);
if(op==1)insert(x);
else if(op==2)del(x);
else if(op==3)printf("%d\n",rnk(rt,x)-1);
else if(op==4)printf("%d\n",kth(rt,x+1));
else if(op==5){predecessor(rt,x);printf("%d\n",v[pred]);}
else if(op==6){successor(rt,x);printf("%d\n",v[succ]);}
}
}
像这样删除,一开始要放进去两个上下限,然后统计的时候记得要绕开。
SBT
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
struct node{
int lc,rc,sz,v;
}tree[500010];
int n,op,x,pred,succ,cnt,rt;
char c;
inline void GET(int &n)
{
n=0;
int f=1;
do{c=getchar();if(c=='-')f=-1;}while(c>'9'||c<'0');
while(c<='9'&&c>='0'){n=n*10+c-'0';c=getchar();}
n*=f;
}
inline void zig(int &r)
{
int t=tree[r].lc;
tree[r].lc=tree[t].rc;
tree[t].rc=r;
tree[r].sz=tree[tree[r].lc].sz+tree[tree[r].rc].sz+1;
tree[t].sz=tree[tree[t].lc].sz+tree[tree[t].rc].sz+1;
r=t;
}
inline void zag(int &r)
{
int t=tree[r].rc;
tree[r].rc=tree[t].lc;
tree[t].lc=r;
tree[r].sz=tree[tree[r].lc].sz+tree[tree[r].rc].sz+1;
tree[t].sz=tree[tree[t].lc].sz+tree[tree[t].rc].sz+1;
r=t;
}
inline void zigzag(int &r)
{
zig(tree[r].rc);
zag(r);
}
inline void zagzig(int &r)
{
zag(tree[r].lc);
zig(r);
}
inline void maintain(int &r,bool flag)
{
if(!flag)
{
if(tree[tree[r].rc].sz<tree[tree[tree[r].lc].lc].sz)zig(r);
else if(tree[tree[r].rc].sz<tree[tree[tree[r].lc].rc].sz)zagzig(r);
else return;
}
else
{
if(tree[tree[r].lc].sz<tree[tree[tree[r].rc].rc].sz)zag(r);
else if(tree[tree[r].lc].sz<tree[tree[tree[r].rc].lc].sz)zigzag(r);
else return;
}
maintain(tree[r].lc,0);
maintain(tree[r].rc,1);
maintain(r,0);
maintain(r,1);
}
void insert(int &r,int x)
{
if(0==r)
{
tree[++cnt].sz=1;
tree[cnt].v=x;
r=cnt;
return;
}
++tree[r].sz;
if(x<tree[r].v)insert(tree[r].lc,x);
else insert(tree[r].rc,x);
maintain(r,x>=tree[r].v);
}
int del(int &r,int x)
{
int res;
--tree[r].sz;
if(tree[r].v==x||(0==tree[r].lc&&x<tree[r].v)||(0==tree[r].rc&&x>tree[r].v))
{
res=tree[r].v;
if(0==tree[r].lc||0==tree[r].rc)r=tree[r].lc+tree[r].rc;
else tree[r].v=del(tree[r].lc,x);
}
else
{
if(x<tree[r].v)res=del(tree[r].lc,x);
else res=del(tree[r].rc,x);
}
return res;
}
void predecessor(int r,int x)
{
if(0==r)return;
if(x>tree[r].v)
{
pred=tree[r].v;
predecessor(tree[r].rc,x);
}
else predecessor(tree[r].lc,x);
}
void successor(int r,int x)
{
if(0==r)return;
if(x<tree[r].v)
{
succ=tree[r].v;
successor(tree[r].lc,x);
}
else successor(tree[r].rc,x);
}
int kth(int r,int x)
{
if(x==tree[tree[r].lc].sz+1)return tree[r].v;
if(x<tree[tree[r].lc].sz+1)return kth(tree[r].lc,x);
return kth(tree[r].rc,x-tree[tree[r].lc].sz-1);
}
int rnk(int r,int x)
{
if(r==0)return 1;
if(x<=tree[r].v)return rnk(tree[r].lc,x);
return rnk(tree[r].rc,x)+tree[tree[r].lc].sz+1;
}
int main()
{
GET(n);
while(n--)
{
GET(op);GET(x);
if(op==1)insert(rt,x);
else if(op==2)del(rt,x);
else if(op==3)printf("%d\n",rnk(rt,x));
else if(op==4)printf("%d\n",kth(rt,x));
else if(op==5){predecessor(rt,x);printf("%d\n",pred);}
else if(op==6){successor(rt,x);printf("%d\n",succ);}
}
}