• [ZJOI2006]书架


    Time Limit: 4 Sec  Memory Limit: 64 MB

    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

    题解:

    我们将所有的书按照在书架中的位置建一棵splay,然后对于题目中的操作。

    1.top

    找到当前点并旋转到根,将它的左子树链接到它的后继的左子树。

    2.bottom

    找到当前点并旋转到根,将它的右子树链接到它的前驱的右子树。

    3.insert

    找到它的前驱或者后继,然后swap一下里面的信息。

    4.ask

    找到这个店,然后旋转到根,输出左节点的size。

    5.query

    直接在树上查找就好。

    细节的话,前两个操作注意判断一下左子树或右子树是否为空。

      1 //Never forget why you start
      2 #include<iostream>
      3 #include<cstdio>
      4 #include<cstdlib>
      5 #include<cstring>
      6 #include<cmath>
      7 #include<algorithm>
      8 #define ll(x) bst[x].child[0]
      9 #define rr(x) bst[x].child[1]
     10 #define son(x,t) bst[x].child[t]
     11 using namespace std;
     12 int n,m;
     13 int root,cnt;
     14 struct node{
     15   int fa,child[2],x,size;
     16 }bst[100005];
     17 void push_up(int r){
     18   bst[r].size=bst[ll(r)].size+bst[rr(r)].size+1;
     19 }
     20 void rotate(int r,int t){
     21   int fa=bst[r].fa;
     22   son(fa,!t)=son(r,t);bst[son(r,t)].fa=fa;
     23   son(bst[fa].fa,son(bst[fa].fa,1)==fa)=r;bst[r].fa=bst[fa].fa;
     24   son(r,t)=fa;bst[fa].fa=r;
     25   push_up(fa);
     26   push_up(r);
     27 }
     28 void splay(int r,int goal){
     29   int fa=bst[r].fa;
     30   while(fa!=goal){
     31     if(bst[fa].fa==goal)rotate(r,son(fa,0)==r);
     32     else{
     33       int t=son(bst[fa].fa,0)==fa;
     34       if(r==son(fa,t))rotate(r,!t),rotate(r,t);
     35       else rotate(fa,t),rotate(r,t);
     36     }
     37     fa=bst[r].fa;
     38   }
     39   if(goal==0)root=r;
     40 }
     41 int pos[100005];
     42 void insert(int x){
     43   cnt++;pos[x]=cnt;
     44   son(cnt,0)=son(cnt,1)=bst[cnt].fa=0;
     45   bst[cnt].x=x;
     46   bst[cnt].size=1;
     47   if(cnt>1){
     48     bst[cnt].fa=cnt-1;
     49     son(cnt-1,1)=cnt;
     50     splay(cnt,0);
     51   }
     52 }
     53 int find(int root,int k){
     54   int y=bst[son(root,0)].size;
     55   if(y+1==k)return root;
     56   else if(y>=k)return find(son(root,0),k);
     57   else return find(son(root,1),k-y-1);
     58 }
     59 void top(int x){
     60   x=pos[x];
     61   splay(x,0);
     62   if(bst[son(x,0)].size==0)return;
     63   if(bst[son(x,1)].size==0){son(x,1)=son(x,0);son(x,0)=0;bst[son(x,1)].fa=x;return;}
     64   else{
     65     int y=find(root,bst[son(x,0)].size+2);
     66     son(y,0)=son(x,0);
     67     bst[son(x,0)].fa=y;
     68     son(x,0)=0;
     69     splay(y,0);
     70   }
     71 }
     72 void bottom(int x){
     73   x=pos[x];
     74   splay(x,0);
     75   if(bst[son(x,1)].size==0)return;
     76   if(bst[son(x,0)].size==0){son(x,0)=son(x,1);son(x,1)=0;bst[son(x,0)].fa=x;return;}
     77   else{
     78     int y=find(root,bst[son(x,0)].size);
     79     son(y,1)=son(x,1);
     80     bst[son(x,1)].fa=y;
     81     son(x,1)=0;
     82     splay(y,0);
     83   }
     84 }
     85 void ins(int x,int t){
     86   int a=x,b;
     87   if(!t)return;
     88   x=pos[x];
     89   splay(x,0);
     90   if(t==1){
     91     if(son(x,1)==0)return;
     92     int y=find(root,bst[son(x,0)].size+2);
     93     b=bst[y].x;
     94     swap(bst[x].x,bst[y].x);
     95     swap(pos[a],pos[b]);
     96     splay(y,0);
     97   }
     98   else{
     99     if(son(x,0)==0)return;
    100     int y=find(root,bst[son(x,0)].size);
    101     b=bst[y].x;
    102     swap(bst[x].x,bst[y].x);
    103     swap(pos[a],pos[b]);
    104     splay(y,0);
    105   }
    106 }
    107 int ask(int x){
    108   x=pos[x];
    109   splay(x,0);
    110   return bst[son(x,0)].size;
    111 }
    112 int query(int x){
    113   return bst[find(root,x)].x;
    114 }
    115 int main(){
    116   int i,j;
    117   root=0;
    118   scanf("%d%d",&n,&m);
    119   for(i=1;i<=n;i++){
    120     scanf("%d",&j);
    121     insert(j);
    122   }
    123   for(i=1;i<=m;i++){
    124     char s[10];
    125     int x;
    126     scanf("%s%d",s,&x);
    127     if(s[0]=='T')top(x);
    128     if(s[0]=='B')bottom(x);
    129     if(s[0]=='I'){
    130       int k;
    131       scanf("%d",&k);
    132       ins(x,k);
    133     }
    134     if(s[0]=='A')printf("%d
    ",ask(x));
    135     if(s[0]=='Q')printf("%d
    ",query(x));
    136   }
    137   return 0;
    138 }
  • 相关阅读:
    Java实现 LeetCode 440 字典序的第K小数字
    Java实现 LeetCode 438 找到字符串中所有字母异位词
    route命令详解与使用实例
    Google protobuf的安装及使用
    linux内核驱动中_IO, _IOR, _IOW, _IOWR 宏的用法与解析
    _GUN_SOURCE宏
    CodeViz产生函数调用图
    linux下阅读源代码的工具
    linux gcc 编译时头文件和库文件搜索路径
    Makefile第四讲:include 引用其它makefile文件
  • 原文地址:https://www.cnblogs.com/huangdalaofighting/p/8256764.html
Copyright © 2020-2023  润新知