[题解]bzoj 1861 Book 书架 - Splay
Posted 阿波罗2003
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[题解]bzoj 1861 Book 书架 - Splay相关的知识,希望对你有一定的参考价值。
1861: [Zjoi2006]Book 书架
Time Limit: 4 Sec Memory Limit: 64 MBSubmit: 1396 Solved: 803
[Submit][Status][Discuss]
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
数据范围
Source
将用Splay按照下标来建树,另外用一个数组来记录编号为i的书在Splay中的位置(指针)。
Top、Bottom和Insert操作就把该节点删掉,然后重新取出来,然后插到对应的位置。
Ask操作把对应节点伸展到根,然后求左子树的大小。Query操作就求K小值就行了。
Code
1 /** 2 * bzoj 3 * Problem#1861 4 * Accepted 5 * Time:1280ms 6 * Memory:3464k 7 */ 8 #include<iostream> 9 #include<fstream> 10 #include<sstream> 11 #include<cstdio> 12 #include<cstdlib> 13 #include<cstring> 14 #include<ctime> 15 #include<cctype> 16 #include<cmath> 17 #include<algorithm> 18 #include<stack> 19 #include<queue> 20 #include<set> 21 #include<map> 22 #include<vector> 23 using namespace std; 24 typedef bool boolean; 25 #define smin(a, b) (a) = min((a), (b)) 26 #define smax(a, b) (a) = max((a), (b)) 27 template<typename T> 28 inline void readInteger(T& u){ 29 char x; 30 int aFlag = 1; 31 while(!isdigit((x = getchar())) && x != ‘-‘ && x != -1); 32 if(x == -1) return; 33 if(x == ‘-‘){ 34 x = getchar(); 35 aFlag = -1; 36 } 37 for(u = x - ‘0‘; isdigit((x = getchar())); u = (u << 3) + (u << 1) + x - ‘0‘); 38 ungetc(x, stdin); 39 u *= aFlag; 40 } 41 42 template<typename T> 43 class SplayNode{ 44 public: 45 T data; 46 int s; 47 SplayNode* next[2]; 48 SplayNode* father; 49 SplayNode(T data, SplayNode* father):data(data), father(father), s(1){ 50 memset(next, 0, sizeof(next)); 51 } 52 inline void maintain(){ 53 this->s = 1; 54 for(int i = 0; i < 2; i++) 55 if(next[i] != NULL) 56 s += next[i]->s; 57 } 58 int which(SplayNode* p){ 59 return (next[0] == p) ? (0) : (1); 60 } 61 }; 62 63 template<typename T> 64 class Splay{ 65 protected: 66 inline static void rotate(SplayNode<T>*& node, int d){ 67 SplayNode<T> *father = node->father; 68 SplayNode<T> *newRoot = node->next[d ^ 1]; 69 node->next[d ^ 1] = newRoot->next[d]; 70 node->father = newRoot; 71 newRoot->next[d] = node; 72 newRoot->father = father; 73 if(node->next[d ^ 1] != NULL) node->next[d ^ 1]->father = node; 74 if(father != NULL) father->next[father->which(node)] = newRoot; 75 node->maintain(); 76 node->father->maintain(); 77 } 78 79 static SplayNode<T>* findKth(SplayNode<T>*& node, int k){ 80 int ls = (node->next[0] != NULL) ? (node->next[0]->s) : (0); 81 if(k == ls + 1) return node; 82 if(k <= ls) return findKth(node->next[0], k); 83 return findKth(node->next[1], k - ls - 1); 84 } 85 86 public: 87 SplayNode<T>* root; 88 89 Splay():root(NULL){ } 90 91 inline void splay(SplayNode<T>*& node, SplayNode<T>* father){ 92 while(node->father != father){ 93 SplayNode<T>* f = node->father; 94 int fd = f->which(node); 95 SplayNode<T>* ff = f->father; 96 if(ff == father){ 97 rotate(f, fd ^ 1); 98 break; 99 } 100 int ffd = ff->which(f); 101 if(fd == ffd){ 102 rotate(ff, ffd ^ 1); 103 rotate(f, fd ^ 1); 104 }else{ 105 rotate(f, fd ^ 1); 106 rotate(ff, ffd ^ 1); 107 } 108 } 109 if(father == NULL) 110 root = node; 111 } 112 113 inline SplayNode<T>* findKth(int k, SplayNode<T>* father){ 114 if(root == NULL || k < 1 || k > root->s) return NULL; 115 SplayNode<T>* res = findKth(root, k); 116 splay(res, father); 117 return res; 118 } 119 120 inline void insert(T data, int index){ 121 if(root == NULL){ 122 root = new SplayNode<T>(data, NULL); 123 return; 124 } 125 SplayNode<T>* added; 126 if(index <= 1){ 127 findKth(1, NULL); 128 added = root->next[0] = new SplayNode<T>(data, root); 129 }else if(index >= root->s + 1){ 130 findKth(root->s, NULL); 131 added = root->next[1] = new SplayNode<T>(data, root); 132 }else if(index == root->s){ 133 findKth(index, NULL); 134 findKth(index - 1, root); 135 added = new SplayNode<T>(data, root); 136 added->next[0] = root->next[0]; 137 root->next[0]->father = added; 138 root->next[0] = added; 139 }else{ 140 findKth(index - 1, NULL); 141 findKth(index + 1, root); 142 SplayNode<T>* node = root->next[1]->next[0]; 143 added = node->next[0] = new SplayNode<T>(data, node); 144 } 145 splay(added, NULL); 146 } 147 148 inline void remove(SplayNode<T>* node){ 149 splay(node, NULL); 150 SplayNode<T>* maxi = node->next[0]; 151 if(maxi == NULL){ 152 root = node->next[1]; 153 if(node->next[1] != NULL) node->next[1]->father = NULL; 154 delete node; 155 return; 156 } 157 while(maxi->next[1] != NULL) maxi = maxi->next[1]; 158 splay(maxi, node); 159 maxi->next[1] = node->next[1]; 160 if(node->next[1] != NULL) node->next[1]->father = maxi; 161 maxi->father = NULL; 162 delete node; 163 root = maxi; 164 maxi->maintain(); 165 } 166 167 }; 168 169 int n, m; 170 Splay<int> s; 171 SplayNode<int>** books; 172 173 inline void init(){ 174 readInteger(n); 175 readInteger(m); 176 books = new SplayNode<int>*[(const int)(n + 1)]; 177 for(int i = 1, a; i <= n; i++){ 178 readInteger(a); 179 s.insert(a, i); 180 books[a] = s.root; 181 } 182 } 183 184 inline void solve(){ 185 char cmd[10]; 186 int a, b; 187 while(m--){ 188 scanf("%s", cmd); 189 readInteger(a); 190 if(cmd[0] == ‘T‘){ 191 s.remove(books[a]); 192 s.insert(a, 1); 193 books[a] = s.root; 194 }else if(cmd[0] == ‘B‘){ 195 s.remove(books[a]); 196 s.insert(a, n); 197 books[a] = s.root; 198 }else if(cmd[0] == ‘I‘){ 199 readInteger(b); 200 if(b == 0) continue; 201 s.splay(books[a], NULL); 202 int r = (s.root->next[0] == NULL) ? (0) : (s.root->next[0]->s); 203 s.remove(books[a]); 204 s.insert(a, r + 1 + b); 205 books[a] = s.root; 206 }else if(cmd[0] == ‘A‘){ 207 s.splay(books[a], NULL); 208 int r = (s.root->next[0] == NULL) ? (0) : (s.root->next[0]->s); 209 printf("%d\n", r); 210 }else if(cmd[0] == ‘Q‘){ 211 SplayNode<int> *node = s.findKth(a, NULL); 212 printf("%d\n", node->data); 213 } 214 } 215 } 216 217 int main(){ 218 init(); 219 solve(); 220 return 0; 221 }
以上是关于[题解]bzoj 1861 Book 书架 - Splay的主要内容,如果未能解决你的问题,请参考以下文章
[bzoj1861][Zjoi2006]Book 书架_非旋转Treap