普通平衡树 替罪羊树模板
不平衡时暴力重构子树,可以说很少写且跑得很快
//Achen
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<vector>
#include<queue>
#include<ctime>
#include<cmath>
const int N=100007*20;
typedef long long LL;
typedef double db;
using namespace std;
int T,o,xx,rt;
namespace RD{
const int sz=1<<15|1;
char ch,buf[sz],*l,*r;
void gechar(char &c) {
if(l==r) r=(l=buf)+fread(buf,1,sz,stdin);
c = l==r?EOF:*l++;
}
template<typename T> void read(T &x) {
gechar(ch); x=0; T f=1;
while(ch!='-'&&(ch<'0'||ch>'9')) gechar(ch);
if(ch=='-') f=-1,gechar(ch);
for(;ch>='0'&&ch<='9';gechar(ch)) x=x*10+ch-'0'; x*=f;
}
}
int tot,ch[N][2],p[N],v[N],sz[N],E[N];
#define lc ch[x][0]
#define rc ch[x][1]
int update(int x) {sz[x]=sz[lc]+sz[rc]+1;}
int bal(int x) {
return 0.75*sz[x]>=(db)sz[lc]&&0.75*sz[x]>=(db)sz[rc];
}
int findx(int y) {
for(int x=rt;x;) {
if(v[x]==y) return x;
if(v[x]<y) x=rc;
else x=lc;
}
}
void tra(int x){
if(lc) tra(lc);
E[++E[0]]=x;
if(rc) tra(rc);
}
int build(int l,int r) {
if(l>r) return 0;
int mid=(l+r)>>1;
int x=E[mid];
lc=build(l,mid-1); p[lc]=x;
rc=build(mid+1,r); p[rc]=x;
update(x);
return x;
}
void rebuild(int x) {
E[0]=0; tra(x);
int y=p[x],z=build(1,E[0]);
if(y) ch[y][x==ch[y][1]]=z; p[z]=y;
if(x==rt) rt=z;
}
int cre(int y) {
int x=++tot;
v[x]=y;
sz[x]=1;
return x;
}
void insert(int y) {
int fa=0,l=1,z=cre(y);
for(int x=rt;;) {
if(!x) {
x=z; p[x]=fa;
if(fa) ch[fa][l]=x;
else rt=x;
break;
}
sz[x]++;
if(v[x]<y) fa=x,l=1,x=rc;
else fa=x,l=0,x=lc;
}
int tp=0;
for(int x=z;x;x=p[x]) if(!bal(x)) tp=x;
if(tp) rebuild(tp);
}
void del(int x) {
if(lc&&rc) {
int y=lc;
while(ch[y][1]) y=ch[y][1];
v[x]=v[y];
x=y;
}
int son=lc?lc:rc;
p[son]=p[x];
if(p[x]) ch[p[x]][x==ch[p[x]][1]]=son;
else rt=son;
for(int i=p[son];i;i=p[i]) sz[i]--;
}
int rank(int y) {
int res=1;
for(int x=rt;x;) {
if(v[x]<y) res+=sz[lc]+1,x=rc;
else x=lc;
}
return res;
}
int kth(int y) {
for(int x=rt;x;) {
if(sz[lc]+1==y) return v[x];
if(sz[lc]+1<y) y-=(sz[lc]+1),x=rc;
else x=lc;
}
}
int pre(int y) {
int res=-1;
for(int x=rt;x;) {
if(v[x]<y) res=v[x],x=rc;
else x=lc;
}
return res;
}
int nxt(int y) {
int res=-1;
for(int x=rt;x;) {
if(v[x]>y) res=v[x],x=lc;
else x=rc;
}
return res;
}
int main() {
RD::read(T);
while(T--) {
RD::read(o); RD::read(xx);
switch(o) {
case 1:insert(xx);break;
case 2:del(findx(xx));break;
case 3:printf("%d\n",rank(xx));break;
case 4:printf("%d\n",kth(xx));break;
case 5:printf("%d\n",pre(xx));break;
case 6:printf("%d\n",nxt(xx));break;
}
}
return 0;
}