【BZOJ1861】【splay】Book 书架

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

 

Source

Zjoi2006
【分析】
基本是裸的splay,
找编号弄一个映射过去就好了。
动态内存分配大法好....
  1 /*
  2 唐代李白
  3 《江夏别宋之悌》
  4 楚水清若空,遥将碧海通。人分千里外,兴在一杯中。
  5 谷鸟吟晴日,江猿啸晚风。平生不下泪,于此泣无穷.
  6 */
  7 #include <iostream>
  8 #include <cstdio>
  9 #include <algorithm>
 10 #include <cstring>
 11 #include <vector>
 12 #include <utility>
 13 #include <iomanip>
 14 #include <string>
 15 #include <cmath>
 16 #include <queue>
 17 #include <assert.h>
 18 #include <map>
 19 #include <ctime>
 20 #include <cstdlib>
 21 #include <stack>
 22 #include <set> 
 23 #define LOCAL
 24 const int INF = 0x7fffffff;
 25 const int MAXN = 80000  + 10;
 26 const int maxnode = 20000 * 2 + 200000 * 20;
 27 const int MAXM = 50000 + 10;
 28 const int MAX = 100000000;
 29 using namespace std;
 30 struct Node {
 31        int siz;
 32        int val;//val代表数的编号 
 33        Node *parent, *ch[2];
 34        
 35        int cmp(){
 36            if (parent->ch[0] == this) return 0;
 37            else return 1;
 38        }
 39 }*root, mem[MAXN * 2], *book[MAXN * 2];//book为编号映射 
 40 int tot, n, m;
 41 
 42 Node *NEW(int val){
 43      Node *t = new Node;
 44      t->val = val;
 45      t->siz = 1;
 46      t->parent = t->ch[0] = t->ch[1] = NULL;
 47      return t;
 48 }
 49 void update(Node *&t){
 50      if (t == NULL) return;
 51      t->siz = 1;
 52      if (t->ch[0] != NULL) t->siz += t->ch[0]->siz;
 53      if (t->ch[1] != NULL) t->siz += t->ch[1]->siz;
 54      return ; 
 55 }
 56 void rotate(Node *t, int d){
 57      if (t->parent == NULL) return;//根就没必要旋转了
 58       
 59      Node *p = t->parent;
 60      p->ch[d ^ 1] = t->ch[d];
 61      if (t->ch[d] != NULL) t->ch[d]->parent = p;
 62      t->parent = p->parent;
 63      if (p->parent != NULL){
 64         if (p->parent->ch[1] == p) p->parent->ch[1] = t;
 65         else if (p->parent->ch[0] == p) p->parent->ch[0] = t;
 66      } 
 67      t->ch[d] = p;
 68      p->parent = t;
 69      update(p);
 70      update(t);
 71      if (root == p) root = t;
 72 }
 73 //将x旋转到y的子树,自己都不知道转成什么样子了... 
 74 void splay(Node *x, Node *y){
 75      while (x->parent != y){
 76            if (x->parent->parent == y){
 77               rotate(x, x->cmp() ^ 1);
 78            }else{
 79               Node *t = x->parent;
 80               //之字形
 81               if (t->ch[t->cmp() ^ 1] == x) rotate(x, x->cmp()^1);
 82               else rotate(t, t->cmp() ^ 1);
 83               rotate(x, x->cmp() ^ 1);
 84            }
 85            update(x);
 86      } 
 87      update(x);
 88 }
 89 //找到第k小然后splay上去 
 90 void find(Node *y, int k){
 91       Node *t = root;
 92       while (1){
 93             if (t->siz == 1) break;
 94             int c = (t->ch[0] == NULL ? 0 : t->ch[0]->siz);
 95             if (c + 1 == k) break;
 96             if (c  >= k ) t = t->ch[0];
 97             else {t = t->ch[1], k -= c + 1;}
 98       }
 99       splay(t, y);
100 }
101 //插入到第pos个位置 
102 void insert(Node *t, int pos, int val){
103      find(NULL, pos + 1);
104      find(root, pos + 2);
105      
106      Node *p = NEW(val);
107      root->ch[1]->ch[0] = p;
108      p->parent = root->ch[1];
109      book[val] = p;
110      splay(p, NULL); 
111 }
112 //找到元素val在t中是第几个 
113 int kth(Node *t, int val){
114     splay(book[val], NULL);
115     return root->ch[0]->siz; //不要忘了还有个INF在前面,哈哈哈 
116 }
117 void erase(Node *t, int pos){
118      find(NULL, pos);
119      find(root, pos + 2);
120      Node *p = root->ch[1]->ch[0];
121      p->parent = NULL;
122      root->ch[1]->ch[0] = NULL;
123      delete(p);
124 }
125 
126 void init(){
127      tot = 0;
128      root = NULL;
129      root = NEW(-INF);
130      root->ch[1] = NEW(INF);
131      root->ch[1]->parent = root;
132      update(root);
133      
134      //find(NULL, 2);
135      //printf("%d", root->val);
136      scanf("%d%d", &n, &m);
137      for (int i = 1; i <= n; i++){
138          int t;
139          scanf("%d", &t);
140          insert(root, i - 1, t);
141      }
142      //printf("%d", kth(root, 10));
143 }
144 void work(){
145      for (int i = 1; i <= m; i++){
146          char str[10];
147          scanf("%s", str);
148          if (str[0] == 'T'){//无论任何时候都有n本书
149             int t;
150             scanf("%d", &t); 
151             erase(root, kth(root, t));
152             insert(root, 0, t);
153          }else if (str[0] == 'B'){
154             int t;
155             scanf("%d", &t);
156             erase(root, kth(root, t));
157             insert(root, n - 1, t);
158          }else if (str[0] == 'A'){
159             int t;
160             scanf("%d", &t);
161             printf("%d\n", kth(root, t) - 1);
162          }else if (str[0] == 'Q'){
163             int t;
164             scanf("%d", &t);
165             find(NULL, t + 1);
166             printf("%d\n", root->val);
167          }else{//修改 
168             int s, t;
169             scanf("%d%d", &s, &t);
170             if (t == 0) continue;//不动
171             int tmp = kth(root, s);//记录s当前的位置 
172             erase(root, tmp);
173             if (t == -1) insert(root, tmp - 2, s);
174             else insert(root, tmp, s);
175          }
176      }
177 }
178 
179 int main(){
180     
181     init();
182     work();
183     return 0;
184 }
View Code

 

posted @ 2015-03-17 21:31  TCtower  阅读(199)  评论(0编辑  收藏  举报