分析:
第一次看这道题的时候,按照数组中的顺序建立splay
但是一时脑抽,想不到怎么查找编号为S的书在哪个结点
过了大约一周,又来看这道题,发现一周之前的我是那么的simple&naive
在splay中,我们无论怎么splay||rotate,每个结点内包含的信息是不会变得,变动的只有结点之间的关系
也就是说,我们只要用一个数组pos,记录一下每个编号在splay中位于哪个结点
我们在删除结点的时候,不要用clear,而是继续使用这个结点(不重新申请结点,注意ch,pre,sz的信息要初始化)
这样就可以解决给出编号的询问了
tip
于是写完了之后,交上去:70
这是怎么回事呐?
注意我对于insert的定义:
当遇到Bottom等操作的时候,在ta上面有n-1本书
//这里写代码片
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
const int N=80010;
int v[N],ch[N][2],sz[N],pre[N];
int n,m,a[N],root,top=0,pos[N];
int get(int bh)
{
return ch[pre[bh]][0]==bh ? 0:1;
}
void update(int bh)
{
if (!bh) return;
sz[bh]=1;
if (ch[bh][0]) sz[bh]+=sz[ch[bh][0]];
if (ch[bh][1]) sz[bh]+=sz[ch[bh][1]];
}
void rotate(int bh)
{
int fa=pre[bh];
int grand=pre[fa];
int wh=get(bh);
ch[fa][wh]=ch[bh][wh^1];
pre[ch[fa][wh]]=fa;
ch[bh][wh^1]=fa;
pre[fa]=bh;
pre[bh]=grand;
if (grand) ch[grand][ch[grand][0]==fa ? 0:1]=bh;
update(fa);
update(bh);
}
void splay(int bh,int mb)
{
for (int fa;(fa=pre[bh])!=mb;rotate(bh))
if (pre[fa]!=mb)
rotate(get(bh)==get(fa)? fa:bh);
if (!mb) root=bh;
}
int build(int l,int r,int fa)
{
if (l>r) return 0;
int mid=(l+r)>>1;
int now=++top;
ch[now][0]=build(l,mid-1,now);
ch[now][1]=build(mid+1,r,now);
v[now]=a[mid]; pre[now]=fa;
update(now);
return now;
}
int find(int x) //排名为x的结点编号
{
int now=root;
while (1)
{
if (ch[now][0]&&sz[ch[now][0]]>=x) now=ch[now][0];
else
{
int tmp=(ch[now][0]? sz[ch[now][0]]:0);
tmp++;
if (x<=tmp) return now;
x-=tmp;
now=ch[now][1];
}
}
}
int fro()
{
int now=ch[root][0];
while (ch[now][1]) now=ch[now][1];
return now;
}
int nxt()
{
int now=ch[root][1];
while (ch[now][0]) now=ch[now][0];
return now;
}
void insert(int x,int p) //上面有x本书,当前插入的是p结点
{
if (x==0)
{
splay(find(x),0);
ch[root][0]=p; pre[p]=root;
update(root);
return;
}
if (x==n-1)
{
splay(find(x),0);
ch[root][1]=p; pre[p]=root;
update(root);
return;
}
splay(find(x),0);
int ls=nxt();
splay(ls,root);
ch[ls][0]=p; pre[p]=ls;
update(ls);
update(root);
}
void del() //删除根结点
{
if (!ch[root][0]&&!ch[root][1])
{
root=0;
return;
}
if (!ch[root][0])
{
root=ch[root][1];
pre[root]=0;
return;
}
if (!ch[root][1])
{
root=ch[root][0];
pre[root]=0;
return;
}
int k=root;
int pr=fro();
splay(pr,0);
ch[root][1]=ch[k][1];
pre[ch[k][1]]=root;
update(root);
return;
}
int main()
{
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++) scanf("%d",&a[i]);
root=build(1,n,0);
for (int i=1;i<=n;i++) pos[v[i]]=i;
char s[10];
int S,T;
for (int i=1;i<=m;i++)
{
scanf("%s",s);
scanf("%d",&S);
if (s[0]=='T')
{
int num=pos[S]; //在splay中的编号
splay(num,0); del();
sz[num]=1; ch[num][0]=ch[num][1]=pre[num]=0;
insert(0,num);
}
else if (s[0]=='B')
{
int num=pos[S];
splay(num,0); del();
sz[num]=1; ch[num][0]=ch[num][1]=pre[num]=0;
insert(n-1,num);
}
else if (s[0]=='I')
{
scanf("%d",&T);
if (T==0) continue;
int num=pos[S];
splay(num,0);
int sum=sz[ch[root][0]];
del();
sz[num]=1; ch[num][0]=ch[num][1]=pre[num]=0;
insert(sum+T,num);
}
else if (s[0]=='A')
{
splay(pos[S],0);
printf("%d\n",sz[ch[root][0]]);
}
else
{
printf("%d\n",v[find(S)]);
}
}
return 0;
}