书架
思路:将每本书的编号作为其在splay中的编号,在查找点x的rank时将x转至树根左子树大小即是。
Attention:删除一个点,找前驱后继与将右子树直接接在前驱上复杂度是大不相同的。
/**************************************************************
Problem: 1861
User: Etta
Language: C++
Result: Accepted
Time:1440 ms
Memory:2384 kb
****************************************************************/
#include
const int sm = 8e4+10;
const int inf = 0x3f3f3f3f;
int N,M,Rt;
int A[sm],Fa[sm],Sz[sm],Ch[sm][2];
char str[10];
void read(int &x) {
char ch=getchar();x=0;int f=1;
while(ch>'9'||ch<'0') { if(ch=='-')f=-1; ch=getchar(); }
while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
x*=f;
}
bool Son(int x,int fa) {
return Ch[fa][1]==x;
}
void Update(int x) {
if(x) {
Sz[x]=1;
if(Ch[x][0]) Sz[x]+=Sz[Ch[x][0]];
if(Ch[x][1]) Sz[x]+=Sz[Ch[x][1]];
}
}
void Rotate(int x) {
int f=Fa[x],g=Fa[f];
int a=Son(x,f),b=!a;
Ch[f][a]=Ch[x][b];
if(Ch[x][b]) Fa[Ch[x][b]]=f;
Ch[x][b]=f,Fa[f]=x;
Fa[x]=g;
if(g) Ch[g][Son(f,g)]=x;
else Rt=x;
Update(f),Update(x);
}
void Splay(int x,int p) {
while(Fa[x]!=p) {
int f=Fa[x],g=Fa[f];
if(g==p) Rotate(x);
else if(Son(x,f)^Son(f,g))
Rotate(x),Rotate(x);
else Rotate(f),Rotate(x);
}
}
void Build(int &rt,int l,int r) {
if(l==r) { rt=A[l],Sz[rt]=1; return ; }
int m=(l+r)>>1; rt=A[m];
if(l<=m-1) Build(Ch[rt][0],l,m-1);
if(r>=m+1) Build(Ch[rt][1],m+1,r);
Fa[Ch[rt][0]]=Fa[Ch[rt][1]]=rt;
Sz[rt]=Sz[Ch[rt][0]]+Sz[Ch[rt][1]]+1;
}
int Pre() {
int now=Ch[Rt][0];
while(Ch[now][1]) now=Ch[now][1];
return now;
}
void del(int x) {
Fa[x]=Ch[x][0]=Ch[x][1]=Sz[x]=0; return;
}
int Find(int rt,int k) {
if(Sz[Ch[rt][0]]+1==k) { Splay(rt,0);return rt; }
if(Sz[Ch[rt][0]]+1return Find(Ch[rt][1],k-Sz[Ch[rt][0]]-1);
return Find(Ch[rt][0],k);
}
void DI(int x,int rnk,bool ind) {
Splay(x,0);
if(ind) rnk+=Sz[Ch[x][0]]+1;
if(Ch[x][0]*Ch[x][1]==0) {
Rt=Ch[x][0]+Ch[x][1];
Fa[Rt]=0,del(x);
}
else {
int pre=Pre(); Splay(pre,x);
Ch[pre][1]=Ch[x][1];
Rt=Fa[Ch[x][1]]=pre;
Fa[Rt]=0,del(x),Update(Rt);
}
int a=Find(Rt,rnk-1),b=Find(Rt,rnk);
Splay(a,0),Splay(b,a);
Ch[b][0]=x,Fa[x]=b,Sz[x]=1;
Ch[x][0]=Ch[x][1]=0;
Update(b),Update(a);
}
int main() {
read(N),read(M);
for(int i=1;i<=N;++i) read(A[i]);
A[0]=sm-4,A[N+1]=sm-5,Build(Rt,0,N+1);
for(int i=1,x,y,tmp;i<=M;++i) {
scanf("%s",str),read(x);
if(str[0]=='T') DI(x,2,0);
if(str[0]=='B') DI(x,N+1,0);
if(str[0]=='I') { read(y); if(y) DI(x,y,1); }
if(str[0]=='A') Splay(x,0),printf("%d\n",Sz[Ch[Rt][0]]-1);
if(str[0]=='Q') printf("%d\n",Find(Rt,x+1));
}
return 0;
}