题目描述
小T有一个很大的书柜。这个书柜的构造有些独特,即书柜里的书是从上至下堆放成一列。她用1到n的正整数给每本书都编了号。
小T在看书的时候,每次取出一本书,看完后放回书柜然后再拿下一本。由于这些书太有吸引力了,所以她看完后常常会忘记原来是放在书柜的什么位置。不过小T的记忆力是非常好的,所以每次放书的时候至少能够将那本书放在拿出来时的位置附近,比如说她拿的时候这本书上面有X本书,那么放回去时这本书上面就只可能有X-1、X或X+1本书。
当然也有特殊情况,比如在看书的时候突然电话响了或者有朋友来访。这时候粗心的小T会随手把书放在书柜里所有书的最上面或者最下面,然后转身离开。
久而久之,小T的书柜里的书的顺序就会越来越乱,找到特定的编号的书就变得越来越困难。于是她想请你帮她编写一个图书管理程序,处理她看书时的一些操作,以及回答她的两个提问:(1)编号为X的书在书柜的什么位置;(2)从上到下第i本书的编号是多少。
输入输出格式
输入格式:
第一行有两个数n,m,分别表示书的个数以及命令的条数;第二行为n个正整数:第i个数表示初始时从上至下第i个位置放置的书的编号;第三行到m+2行,每行一条命令。命令有5种形式:
1. Top S——表示把编号为S的书放在最上面。
2. Bottom S——表示把编号为S的书放在最下面。
3. Insert S T——T∈{-1,0,1},若编号为S的书上面有X本书,则这条命令表示把这本书放回去后它的上面有X+T本书;
4. Ask S——询问编号为S的书的上面目前有多少本书。
5. Query S——询问从上面数起的第S本书的编号。
输出格式:
对于每一条Ask或Query语句你应该输出一行,一个数,代表询问的答案。
输入输出样例
10 10
1 3 2 7 5 8 10 4 9 6
Query 3
Top 5
Ask 6
Bottom 3
Ask 3
Top 6
Insert 4 -1
Query 5
Query 2
Ask 2
2
9
9
7
5
3
说明
100%的数据,n,m <= 80000
题解:先依次将点插入splay,权值为x[i]的第i个插入,splay维护的是顺序
显然插入到第x+1本或者第x-1本书的操作是将x的权值与他的后继或者前驱交换
插到底或者顶就是将x的左子树换到他的后继的左子树或者将x的右子树换到他的前驱的右子树
然后就可以用splay瞎搞了
代码如下:
#include<set> #include<map> #include<cmath> #include<queue> #include<stack> #include<vector> #include<cstdio> #include<string> #include<cstring> #include<iostream> #include<algorithm> #define lson ch[x][0] #define rson ch[x][1] #define mod 1000000007 using namespace std; int n,m; int pos[100010],sz[100010],key[100010],f[100010],ch[100010][3],cnt,rt; int push_up(int x) { sz[x]=sz[lson]+sz[rson]+1; pos[key[lson]]=lson; pos[key[rson]]=rson; } int rotate(int x) { int y=f[x],z=f[y],kd=(ch[y][1]==x),xs=ch[x][!kd]; if(z) ch[z][ch[z][1]==y]=x; ch[x][!kd]=y; ch[y][kd]=xs; if(xs) f[xs]=y; f[x]=z; f[y]=x; push_up(y); } int splay(int goal,int x) { int y,z; while(f[x]!=goal) { y=f[x],z=f[y]; if(z!=goal) { (ch[y][0]==x)^(ch[z][0]==y)?rotate(x):rotate(y); } rotate(x); } push_up(x); if(!goal) rt=x; } int insert(int x) { key[++cnt]=x; sz[cnt]=1; pos[x]=cnt; ch[cnt][0]=ch[cnt][1]=0; if(cnt>1) { ch[cnt-1][1]=cnt; f[cnt]=cnt-1; splay(0,cnt); } } int find(int x,int tot) { if(sz[lson]+1==tot) { return x; } else { if(sz[lson]+1<tot) { return find(rson,tot-sz[lson]-1); } else return find(lson,tot); } } int get(int x,int kd) { int y=ch[x][kd]; while(ch[y][!kd]) { y=ch[y][!kd]; } return y; } int make_top(int x) { x=pos[x]; splay(0,x); if(!lson) return 0; if(!rson) swap(lson,rson); else { int y=get(x,1); f[lson]=y; ch[y][0]=lson; lson=0; splay(0,ch[y][0]); } } int make_buttom(int x) { x=pos[x]; splay(0,x); if(!rson) return 0; if(!lson) swap(lson,rson); else { int y=get(x,0); f[rson]=y; ch[y][1]=rson; rson=0; splay(0,ch[y][1]); } } int change(int x,int kd) { if(!kd) return 0; splay(0,pos[x]); int y=(kd==1)?get(pos[x],1):get(pos[x],0); int tmp1=key[y],tmp2=pos[x]; swap(pos[x],pos[tmp1]); swap(key[tmp2],key[y]); } void print(int x) { splay(0,x); printf("%d ",sz[lson]); } void dayin(int x) { printf("%d %d %d ",x,lson,rson); if(lson) dayin(lson); if(rson) dayin(rson); } int main() { ch[0][0]=ch[0][1]=sz[0]=f[0]=key[0]=pos[0]=0; scanf("%d%d",&n,&m); int tmp; for(int i=1; i<=n; i++) { scanf("%d",&tmp); insert(tmp); } string op; while(m--) { cin>>op; int tmp1,tmp2; if(op[0]=='T') { scanf("%d",&tmp1); make_top(tmp1); } if(op[0]=='B') { scanf("%d",&tmp2); make_buttom(tmp2); } if(op[0]=='I') { scanf("%d%d",&tmp1,&tmp2); change(tmp1,tmp2); } if(op[0]=='A') { scanf("%d",&tmp1); print(pos[tmp1]); } if(op[0]=='Q') { scanf("%d",&tmp1); printf("%d ",key[find(rt,tmp1)]); } } }