替罪羊樹(重量平衡樹)
阿新 • • 發佈:2019-02-19
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
#define LL long long
using namespace std;
inline int read(){
int x=0,f=1;char ch=' ';
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while (ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
return x*f;
}
#define ls ch[x][0]
#define rs ch[x][1]
const int N=3e6+5,inf=2e9;
const double alpha=0.75;
int n,sz,root,len;
int cur[N],ch[N][2],f[N],key[N],size[N];
inline bool balance(int x){
return alpha*(double )size[x]>=size[ls] && alpha*(double)size[x]>=size[rs];
}
inline void recycle(int x){
if(ls)recycle(ls);
cur[++len]=x;
if(rs)recycle(rs);
}
inline int build(int l,int r){
if(l>r)return 0;
int mid=(l+r)>>1,x=cur[mid];
ls=build(l,mid-1);if(ls)f[ls]=x;
rs=build(mid+1 ,r);if(rs)f[rs]=x;
size[x]=size[ls]+size[rs]+1;
return x;
}
inline void rebuild(int x){
len=0;recycle(x);
int fa=f[x],w=(ch[f[x]][1]==x);
int cur=build(1,len);
f[cur]=fa;ch[fa][w]=cur;
if(x==root)root=cur;
}
inline void insert(int x){
int now=root,cur=++sz,w;
size[cur]=1;key[cur]=x;
while(1){
++size[now];
w=(x>=key[now]);
if(ch[now][w])now=ch[now][w];
else{
f[ch[now][w]=cur]=now;
break;
}
}
int flag=0;
for(int i=now;i;i=f[i])if(!balance(i))flag=i;
if(flag)rebuild(flag);
}
inline int find(int x){
int now=root;
while(1){
if(key[now]==x)return now;
else now=ch[now][x>key[now]];
}
}
inline void erase(int x){
if(ls && rs){
int cur=ls;
while(ch[cur][1])cur=ch[cur][1];
key[x]=key[cur];x=cur;
}
int cur=(ls)?ls:rs;
int w=(ch[f[x]][1]==x);
f[ch[f[x]][w]=cur]=f[x];
for(int i=f[x];i;i=f[i])--size[i];
if(x==root)root=cur;
}
inline int Rank(int v){
int x=root,ans=0;
while(x){
if(v>key[x])ans+=size[ls]+1,x=rs;
else x=ls;
}
return ans;
}
inline int Kth(int k){
int x=root;
while(1){
if(k==size[ls]+1)return key[x];
else if(k<=size[ls])x=ls;
else k-=size[ls]+1,x=rs;
}
}
inline int Pre(int v){
int x=root,ans=-inf;
while(x){
if(v>key[x])ans=max(ans,key[x]),x=rs;
else x=ls;
}
return ans;
}
inline int Next(int v){
int x=root,ans=inf;
while(x){
if(v<key[x])ans=min(ans,key[x]),x=ls;
else x=rs;
}
return ans;
}
int main(){
key[1]=-inf;key[2]=inf;
size[1]=2;size[2]=1;
ch[1][1]=2;f[2]=1;
sz=2;root=1;
n=read();
for(int i=1;i<=n;++i){
int opt=read(),x=read();
switch(opt){
case 1:insert(x);break;
case 2:erase(find(x));break;
case 3:printf("%d\n",Rank(x));break;
case 4:printf("%d\n",Kth(x+1));break;
case 5:printf("%d\n",Pre(x));break;
case 6:printf("%d\n",Next(x));break;
}
}
return 0;
}