替罪羊树板子
#include <cstdio>
#define ls ch[now][0]
#define rs ch[now][1]
const int N=1e5+10;
double alpha=0.7;
int valit[N],siz[N],exist[N],ch[N][2],dat[N],tot,q[N<<2],l=1,r=0,s[N],cnt,root;
#define bad (siz[now]*alpha<(double)(siz[ls])||siz[now]*alpha<(double)(siz[rs]))
#define updata siz[now]=siz[ls]+siz[rs]+1,valit[now]=valit[ls]+valit[rs]+exist[now]
int New(){return l<=r?q[l++]:++tot;}
void del(int now){q[++r]=now;}
void dfs(int now)
{
if(!now) return;
dfs(ls);
if(exist[now])s[++cnt]=dat[now];
del(now);
dfs(rs);
}
void build(int &now,int l,int r)
{
if(l>r){now=0;return;}
now=New();
int mid=l+r>>1;
dat[now]=s[mid];
exist[now]=1;
build(ls,l,mid-1),build(rs,mid+1,r);
updata;
}
void rebuild(int &now)
{
cnt=0;dfs(now);
build(now,1,cnt);
}
void Insert(int &now,int k)
{
if(!now)
{
now=New();
exist[now]=valit[now]=siz[now]=1;
dat[now]=k;ls=rs=0;
return;
}
++siz[now],++valit[now];
if(dat[now]>=k) Insert(ls,k);
else Insert(rs,k);
if(bad) rebuild(now);
}
int kth(int now,int k)
{
if(!now) return 1;
if(dat[now]>=k) return kth(ls,k);
else return kth(rs,k)+valit[ls]+exist[now];
}
void extrack(int now,int k)
{
--valit[now];
if(k<=valit[ls]) extrack(ls,k);
else if(k>valit[ls]+exist[now]) extrack(rs,k-valit[ls]-exist[now]);
else --exist[now];
}
int fkth(int now,int k)
{
if(k<=valit[ls]) return fkth(ls,k);
else if(k>valit[ls]+exist[now]) return fkth(rs,k-valit[ls]-exist[now]);
else return dat[now];
}
int main()
{
int n;scanf("%d",&n);
for(int opt,x,i=1;i<=n;i++)
{
scanf("%d%d",&opt,&x);
if(opt==1) Insert(root,x);
else if(opt==2) extrack(root,kth(root,x));
else if(opt==3) printf("%d\n",kth(root,x));
else if(opt==4) printf("%d\n",fkth(root,x));
else if(opt==5) printf("%d\n",fkth(root,kth(root,x)-1));
else printf("%d\n",fkth(root,kth(root,x+1)));
}
return 0;
}
码量和FHQ差不过,但目前感觉FHQ好写一点。
复杂度保证有一点是懒惰删除,可以根据朝鲜树感性理解。