书架
平衡树的一点小变通。
要求支持一些操作:询问序列第k个元素是什么,询问元素k在序列中的位置,把一个元素放到序列最前面或最后面,交换两个元素(\(insert\) 操作说白了就是交换这个元素和它前面或后面的元素交换)。
第一个和最后一个还好,其它操作有点麻烦。问题就在于要把节点的点值和节点的编号挂钩,于是就想到用 \(pl[i]\) 来代表元素i对应的节点,在交换元素的时候就把pl对应的元素交换,把对应节点的点权交换一下即可。至于询问元素i在序列中的位置,直接暴力向上跳即可。
是要splay的,而且最好顺便splay一个随机节点。玄学方法过的。随机Splay主要是因为把元素丢到序列最前面和最后面的时候涉及到删除和插入操作。
#include<bits/stdc++.h>
//#define zczc
const int N=80010;
using namespace std;
inline void read(int &wh){
wh=0;int f=1;char w=getchar();
while(w<'0'||w>'9'){if(w=='-')f=-1;w=getchar();}
while(w<='9'&&w>='0'){wh=wh*10+w-'0';w=getchar();}
wh*=f;return;
}
inline void swap(int &s1,int &s2){
int s3=s1;s1=s2;s2=s3;
}
#define lc t[x].ch[0]
#define rc t[x].ch[1]
struct node{
int id,size,ch[2],f;
}t[N];
int root;
inline void pushup(int x){
t[x].size=t[lc].size+t[rc].size+1;
}
inline int build(int l,int r,int fa){
//printf("now:%d %d\n",l,r);
if(l>r)return 0;
if(l==r)return t[l].f=fa,t[l].size=1,l;
int x=l+r+1>>1;
t[x].f=fa;
lc=build(l,x-1,x);
rc=build(x+1,r,x);
pushup(x);
return x;
}
inline int work(int x,int come){
//printf("%d %d\n",x,come);
return (x==root?0:work(t[x].f,x))+(come==rc?1+t[lc].size:0);
}
inline int find(int x,int kk){
if(kk<0)return 0;
//printf("now:%d %d\n",x,kk);
if(kk<=t[lc].size)return find(lc,kk);
if(kk==t[lc].size+1)return t[x].id;
return find(rc,kk-t[lc].size-1);
}
inline void rotate(int x){
int y=t[x].f;int z=t[y].f;int kk=t[y].ch[1]==x;int cd=t[x].ch[kk^1];
if(z)t[z].ch[t[z].ch[1]==y]=x;t[x].f=z;
t[cd].f=y;t[y].ch[kk]=cd;
t[x].ch[kk^1]=y;t[y].f=x;
pushup(y);pushup(x);
if(y==root)root=x;
}
inline void splay(int x){
while(t[x].f){
int y=t[x].f;int z=t[y].f;
if(z)(t[z].ch[1]==y)^(t[y].ch[1]==x)?rotate(x):rotate(y);
rotate(x);
}
root=x;
}
void delete_(int x){
while(lc!=0||rc!=0){
if(lc&&rc)rotate(t[x].ch[rand()%2]);
else if(lc)rotate(lc);
else rotate(rc);
//printf("%d %d\n",lc,rc);
}
int ff=t[x].f;
t[ff].ch[t[ff].ch[1]==x]=0;
while(ff)pushup(ff),ff=t[ff].f;
}
void put_l(int wh){
int x=root;
while(lc)x=lc;
lc=wh;t[wh].f=x;
while(x)pushup(x),x=t[x].f;
return;
}
void put_r(int wh){
int x=root;
while(rc)x=rc;
rc=wh;t[wh].f=x;
while(x)pushup(x),x=t[x].f;
return;
}
#undef lc
#undef rc
int m,n,pl[N];//pl:每本书对应哪个节点
signed main(){
#ifdef zczc
freopen("in.txt","r",stdin);
#endif
srand(time(0));
read(m);read(n);
for(int i=1;i<=m;i++){
read(t[i].id);
pl[t[i].id]=i;
}
root=build(1,m,0);
int s1,s2;
while(n--){
char op[20];scanf("%s",op);
switch(op[0]){
case 'Q':
read(s1);
printf("%d\n",find(root,s1));
break;
case 'A':
read(s1);s1=pl[s1];
printf("%d\n",work(s1,t[s1].ch[1])-1);
break;
case 'B':
read(s1);s1=pl[s1];
delete_(s1);
put_r(s1);
//splay(s1);
splay(rand()%m+1);
break;
case 'T':
read(s1);s1=pl[s1];
delete_(s1);put_l(s1);
//splay(s1);
splay(rand()%m+1);
break;
case 'I':
read(s1);read(s2);
if(s2==0)break;
int ap=find(root,work(pl[s1],t[pl[s1]].ch[1])+s2);
swap(pl[s1],pl[ap]);
swap(t[pl[s1]].id,t[pl[ap]].id);
break;
}
}
return 0;
}
一如既往,万事胜意