平衡树一种,基于重构的思想,插入点的时候判断某个子树不平衡到达一定程度就重构成一棵平衡的子树,具体判断不平衡是取一个alpha(约0.75),当某节点max(左子树,右子树)>=alpha×该节点总子树大小就重构。对于有删除操作的题目则维护两个size表示总的(不管删没删)和真实还存在的,在重构时去掉删掉的即可。
代码:
#pragma GCC optimize(3,"inline","Ofast")
#include<bits/stdc++.h>
#define db double
using namespace std;
inline void read(int &x)
{
char c=getchar();x=0;int r=1;
while(!isdigit(c))
{
if(c=='-')r=-1;
c=getchar();
}
while(isdigit(c))x=(x<<3)+(x<<1)+c-48,c=getchar();
x*=r;
}
inline void write(int x)
{if(x<0)putchar('-'),x=-x;if(x>=10)write(x/10);putchar(x%10+'0');}
const int N = 1e5+10;
const db apha = 0.75;
struct gg{
int ch[2],w,tsz,fsz;
bool del;
}node[N];
int bin[2*N],tax[N],rt,pb,pt;
void push_up(int x)
{
node[x].fsz=node[node[x].ch[0]].fsz+node[node[x].ch[1]].fsz+1;
node[x].tsz=node[node[x].ch[0]].tsz+node[node[x].ch[1]].tsz+1;
}
bool check(int x)
{return (db)max(node[node[x].ch[0]].tsz,node[node[x].ch[1]].tsz)>=(db)node[x].tsz*apha;}
void dfs(int pos)
{
if(!pos)return;
dfs(node[pos].ch[0]);
if(!node[pos].del)tax[++pt]=pos;
else bin[++pb]=pos;
dfs(node[pos].ch[1]);
}
void build(int l,int r,int &nw)
{
int mid=(l+r)>>1;
nw=tax[mid];
if(l==r)
{
node[nw].del=0,node[nw].ch[0]=node[nw].ch[1]=0;
node[nw].fsz=node[nw].tsz=1;
return;
}
if(l<mid)build(l,mid-1,node[nw].ch[0]);else node[nw].ch[0]=0;
if(mid<r)build(mid+1,r,node[nw].ch[1]);else node[nw].ch[1]=0;
push_up(nw);
}
void pia(int &nw)
{
pt=0,dfs(nw);
if(pt)build(1,pt,nw);
else nw=0;
}
void ins(int &nw,int v)
{
if(!nw)
{
nw=bin[pb--];node[nw].del=0;node[nw].fsz=node[nw].tsz=1;
node[nw].ch[0]=node[nw].ch[1]=0;node[nw].w=v;
return;
}
node[nw].fsz++,node[nw].tsz++;
if(node[nw].w>=v)ins(node[nw].ch[0],v);
else ins(node[nw].ch[1],v);
if(check(nw))pia(nw);
}
int rnk(int x)
{
int nw=rt,ans=1;
while(nw)
{
if(node[nw].w>=x)nw=node[nw].ch[0];
else
{
ans+=node[node[nw].ch[0]].tsz+(node[nw].del^1);
nw=node[nw].ch[1];
}
}
return ans;
}
int kth(int x)
{
int nw=rt;
while(nw)
{
if(!node[nw].del&&node[node[nw].ch[0]].tsz+1==x)return node[nw].w;
else if(node[node[nw].ch[0]].tsz>=x)nw=node[nw].ch[0];
else x-=node[node[nw].ch[0]].tsz+(node[nw].del^1),nw=node[nw].ch[1];
}
}
void del_pos(int &nw,int to)
{
if(!node[nw].del&&node[node[nw].ch[0]].tsz+1==to)
{
node[nw].del=1,node[nw].tsz--;return;
}
node[nw].tsz--;
if(node[node[nw].ch[0]].tsz>=to)del_pos(node[nw].ch[0],to);//?
else del_pos(node[nw].ch[1],to-node[node[nw].ch[0]].tsz-(node[nw].del^1));
}
void del_v(int nw)
{
del_pos(rt,rnk(nw));
if((db)node[rt].fsz*apha>(db)node[rt].tsz)pia(rt);
}
void init()
{
pb=0;
for(int i=200000;i>=1;i--)bin[++pb]=i;
}
int main()
{
init();
int m,op,x;
read(m);
while(m--)
{
read(op),read(x);
if(op==1)ins(rt,x);
if(op==2)del_v(x);
if(op==3)write(rnk(x)),puts("");
if(op==4)write(kth(x)),puts("");
if(op==5)write(kth(rnk(x)-1)),puts("");
if(op==6)write(kth(rnk(x+1))),puts("");
}
}