zoukankan      html  css  js  c++  java
  • 【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
    ", 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
    ", 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
  • 相关阅读:
    修复火狐主页被篡改成hao123的办法
    VMware中装Win2012并配置Hyper-v
    Linux下随机密码生成器
    GNS3 桥接虚拟网卡 telnet 实验
    冰点文库下载器停止工作解决办法
    《循序渐进》之简单的DHCP实验
    windows脚本配置ip地址
    phpmyadmin使用中碰到的一些问题
    phpmyadmin导入导出大数据文件的办法
    phpmyadmin的安装和使用
  • 原文地址:https://www.cnblogs.com/hoskey/p/4345606.html
Copyright © 2011-2022 走看看