首页 > 代码库 > [题解]bzoj 1861 Book 书架 - Splay

[题解]bzoj 1861 Book 书架 - Splay

1861: [Zjoi2006]Book 书架

Time Limit: 4 Sec  Memory Limit: 64 MB
Submit: 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

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

Day2

[Submit][Status][Discuss]

  将用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