【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

 

你可能感兴趣的:(play)