[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

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

Sample Output

2
9
9
7
5
3

HINT

数据范围

100%的数据,n,m < = 80000

题解:

我们将所有的书按照在书架中的位置建一棵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 }

 

posted @ 2018-01-10 08:13  kakakakakaka  阅读(146)  评论(0编辑  收藏  举报

Never forget why you start

//鼠标爆炸特效