[ZJOI2006]书架
Time Limit: 4 Sec Memory Limit: 64 MB
Description
小T有一个很大的书柜。这个书柜的构造有些独特,即书柜里的书是从上至下堆放成一列。她用1到n的正整数给每本书都编了号。 小T在看书的时候,每次取出一本书,看完后放回书柜然后再拿下一本。由于这些书太有吸引力了,所以她看完后常常会忘记原来是放在书柜的什么位置。不过小T的记忆力是非常好的,所以每次放书的时候至少能够将那本书放在拿出来时的位置附近,比如说她拿的时候这本书上面有X本书,那么放回去时这本书上面就只可能有X-1、X或X+1本书。 当然也有特殊情况,比如在看书的时候突然电话响了或者有朋友来访。这时候粗心的小T会随手把书放在书柜里所有书的最上面或者最下面,然后转身离开。 久而久之,小T的书柜里的书的顺序就会越来越乱,找到特定的编号的书就变得越来越困难。于是她想请你帮她编写一个图书管理程序,处理她看书时的一些操作,以及回答她的两个提问:(1)编号为X的书在书柜的什么位置;(2)从上到下第i本书的编号是多少。
Input
第一行有两个数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本书的编号。
Output
对于每一条Ask或Query语句你应该输出一行,一个数,代表询问的答案。
Sample Input
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
Sample Output
9
9
7
5
3
HINT
数据范围
题解:
我们将所有的书按照在书架中的位置建一棵splay,然后对于题目中的操作。
1.top
找到当前点并旋转到根,将它的左子树链接到它的后继的左子树。
2.bottom
找到当前点并旋转到根,将它的右子树链接到它的前驱的右子树。
3.insert
找到它的前驱或者后继,然后swap一下里面的信息。
4.ask
找到这个店,然后旋转到根,输出左节点的size。
5.query
直接在树上查找就好。
细节的话,前两个操作注意判断一下左子树或右子树是否为空。
1 //Never forget why you start 2 #include<iostream> 3 #include<cstdio> 4 #include<cstdlib> 5 #include<cstring> 6 #include<cmath> 7 #include<algorithm> 8 #define ll(x) bst[x].child[0] 9 #define rr(x) bst[x].child[1] 10 #define son(x,t) bst[x].child[t] 11 using namespace std; 12 int n,m; 13 int root,cnt; 14 struct node{ 15 int fa,child[2],x,size; 16 }bst[100005]; 17 void push_up(int r){ 18 bst[r].size=bst[ll(r)].size+bst[rr(r)].size+1; 19 } 20 void rotate(int r,int t){ 21 int fa=bst[r].fa; 22 son(fa,!t)=son(r,t);bst[son(r,t)].fa=fa; 23 son(bst[fa].fa,son(bst[fa].fa,1)==fa)=r;bst[r].fa=bst[fa].fa; 24 son(r,t)=fa;bst[fa].fa=r; 25 push_up(fa); 26 push_up(r); 27 } 28 void splay(int r,int goal){ 29 int fa=bst[r].fa; 30 while(fa!=goal){ 31 if(bst[fa].fa==goal)rotate(r,son(fa,0)==r); 32 else{ 33 int t=son(bst[fa].fa,0)==fa; 34 if(r==son(fa,t))rotate(r,!t),rotate(r,t); 35 else rotate(fa,t),rotate(r,t); 36 } 37 fa=bst[r].fa; 38 } 39 if(goal==0)root=r; 40 } 41 int pos[100005]; 42 void insert(int x){ 43 cnt++;pos[x]=cnt; 44 son(cnt,0)=son(cnt,1)=bst[cnt].fa=0; 45 bst[cnt].x=x; 46 bst[cnt].size=1; 47 if(cnt>1){ 48 bst[cnt].fa=cnt-1; 49 son(cnt-1,1)=cnt; 50 splay(cnt,0); 51 } 52 } 53 int find(int root,int k){ 54 int y=bst[son(root,0)].size; 55 if(y+1==k)return root; 56 else if(y>=k)return find(son(root,0),k); 57 else return find(son(root,1),k-y-1); 58 } 59 void top(int x){ 60 x=pos[x]; 61 splay(x,0); 62 if(bst[son(x,0)].size==0)return; 63 if(bst[son(x,1)].size==0){son(x,1)=son(x,0);son(x,0)=0;bst[son(x,1)].fa=x;return;} 64 else{ 65 int y=find(root,bst[son(x,0)].size+2); 66 son(y,0)=son(x,0); 67 bst[son(x,0)].fa=y; 68 son(x,0)=0; 69 splay(y,0); 70 } 71 } 72 void bottom(int x){ 73 x=pos[x]; 74 splay(x,0); 75 if(bst[son(x,1)].size==0)return; 76 if(bst[son(x,0)].size==0){son(x,0)=son(x,1);son(x,1)=0;bst[son(x,0)].fa=x;return;} 77 else{ 78 int y=find(root,bst[son(x,0)].size); 79 son(y,1)=son(x,1); 80 bst[son(x,1)].fa=y; 81 son(x,1)=0; 82 splay(y,0); 83 } 84 } 85 void ins(int x,int t){ 86 int a=x,b; 87 if(!t)return; 88 x=pos[x]; 89 splay(x,0); 90 if(t==1){ 91 if(son(x,1)==0)return; 92 int y=find(root,bst[son(x,0)].size+2); 93 b=bst[y].x; 94 swap(bst[x].x,bst[y].x); 95 swap(pos[a],pos[b]); 96 splay(y,0); 97 } 98 else{ 99 if(son(x,0)==0)return; 100 int y=find(root,bst[son(x,0)].size); 101 b=bst[y].x; 102 swap(bst[x].x,bst[y].x); 103 swap(pos[a],pos[b]); 104 splay(y,0); 105 } 106 } 107 int ask(int x){ 108 x=pos[x]; 109 splay(x,0); 110 return bst[son(x,0)].size; 111 } 112 int query(int x){ 113 return bst[find(root,x)].x; 114 } 115 int main(){ 116 int i,j; 117 root=0; 118 scanf("%d%d",&n,&m); 119 for(i=1;i<=n;i++){ 120 scanf("%d",&j); 121 insert(j); 122 } 123 for(i=1;i<=m;i++){ 124 char s[10]; 125 int x; 126 scanf("%s%d",s,&x); 127 if(s[0]=='T')top(x); 128 if(s[0]=='B')bottom(x); 129 if(s[0]=='I'){ 130 int k; 131 scanf("%d",&k); 132 ins(x,k); 133 } 134 if(s[0]=='A')printf("%d\n",ask(x)); 135 if(s[0]=='Q')printf("%d\n",query(x)); 136 } 137 return 0; 138 }