1. 程式人生 > >替罪羊樹(重量平衡樹)

替罪羊樹(重量平衡樹)

#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; }