zoukankan      html  css  js  c++  java
  • BZOJ-1861 Book 书架 Splay

    1861: [Zjoi2006]Book 书架
    Time Limit: 4 Sec Memory Limit: 64 MB
    Submit: 1010 Solved: 588
    [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

    比较裸的Splay,无奈语文差一开始理解错意思了...
    

    操作insert似乎意思是这样的…从他上面取下了书,放回去后放到他的下面,所以-1;从他上面取书又放在他上面,所以为0;没从上面取书,把书放在他上面所以+1;…..
    总之 旋转+伸展(这TM不是废话吗..)+插入+删除+区间查询+单点查 询 即可维护

    code(即本人splay模板…):

    #include <cstdio>
    #include <iostream>
    #include <cstring>
    #include <cmath>
    
    using namespace std;
    
    const int N=80012;
    int n,m,x,y,z;
    char opt,ch;
    struct Snode 
      {
        Snode *lch,*rch,*p;
        int id,size;
        inline void update(){size=lch->size+rch->size+1;}
        inline bool is_l() {return this==p->lch;}
        inline void set_l(Snode *x) {lch=x;x->p=this;}
        inline void set_r(Snode *x) {rch=x;x->p=this;}
        inline void left()
          {
            Snode *fa=p;
            if (fa->is_l()) fa->p->set_l(this);
              else fa->p->set_r(this);
            fa->set_r(lch);set_l(fa);fa->update();
          }
        inline void right()
          {
            Snode *fa=p;
            if (fa->is_l()) fa->p->set_l(this);
              else fa->p->set_r(this);
            fa->set_l(rch);set_r(fa);fa->update();
          }
        inline Snode *rank(int k)
          {
            if (lch->size+1==k) return this;
            if (lch->size+1<k) return rch->rank(k-lch->size-1);
              else return lch->rank(k);
          }
      } T[2*N],*P=T,*nil=T,*root,*pos[N],*ld,*rd;
    inline void newnode(Snode *&node,int x)
      {
        node=++P;
        node->lch=node->rch=node->p=nil;
        node->size=1;node->id=x;
      }
    inline void splay(Snode *&root,Snode *x,Snode *y)
      {
        while (x->p!=y)
          {
            if (x->p->p==y)
              {
                if (x->is_l()) x->right();else x->left();
                break;
              }
            if (x->p->is_l())
              if (x->is_l()) x->p->right(),x->right();
                else x->left(),x->right();
            else
              if (x->is_l()) x->right(),x->left();
                else x->p->left(),x->left();
          }
        x->update();
        if (y==nil) root=x;
      }
    inline Snode *pred(Snode *node)
      {
        splay(root,node,nil);
        Snode *last=nil,*now=node->lch;
        while (now!=nil) last=now,now=now->rch;
        return last;
      }
    inline Snode *succ(Snode *node)
      {
        splay(root,node,nil);
        Snode *last=nil,*now=node->rch;
        while (now!=nil) last=now,now=now->lch;
        return last;
      }
    inline void insert(Snode *node,int k)
      {
        Snode *t1=root->rank(k-1),*t2=root->rank(k);
        splay(root,t2,nil);splay(root,t1,root);
        root->lch->set_r(node);root->lch->update();root->update();
      }
    inline void remove(Snode *&node)
      {
        Snode *t1=pred(node),*t2=succ(node);
        splay(root,t2,nil);splay(root,t1,root);
        root->lch->set_r(nil);root->lch->update();root->update();
        node=nil;
      }
    inline int order(Snode *node)
      {
        splay(root,node,nil);return root->lch->size+1;
      }
    int main()
      {
        nil->id=-1;
        newnode(ld,0);newnode(rd,0);
        root=rd;rd->set_l(ld);ld->update();rd->update();
        scanf("%d%d",&n,&m);
        for (int i=1;i<=n;++i)
          {
            scanf("%d",&x);Snode *tmp=pred(rd);
            splay(root,rd,nil);splay(root,tmp,root);
            newnode(pos[x],x);root->lch->set_r(pos[x]);
            root->lch->update();root->update();
            splay(root,pos[x],nil);
          }
        for (int i=1;i<=m;++i)
          {
            do opt=getchar();while (opt=='
    ' || opt==' ');
            do ch=getchar();while (ch!=' ');
            if (opt=='T') scanf("%d",&x),remove(pos[x]),newnode(pos[x],x),insert(pos[x],2);
            if (opt=='B') scanf("%d",&x),remove(pos[x]),newnode(pos[x],x),insert(pos[x],n+1);
            if (opt=='I') scanf("%d%d",&x,&y),z=order(pos[x]),remove(pos[x]),newnode(pos[x],x),insert(pos[x],z+y);
            if (opt=='A') scanf("%d",&x),printf("%d
    ",order(pos[x])-2);
            if (opt=='Q') scanf("%d",&x),printf("%d
    ",root->rank(x+1)->id);
          }
      }    
  • 相关阅读:
    ROW_NUMBER()用法(转)
    winform MD5值生成
    VC使用“添加方法向导”添加调度映射方法“
    MyGeneration配置说明
    dataGridView取消自动生成列
    PHP魔术常量(magic constant)
    Eclipse添加DTD文件实现xml的自动提示功能
    Google:5个常见的SEO错误和6个SEO好主意
    PHP检查PEAR是否工作
    手把手教你在ubuntu上安装LAMP
  • 原文地址:https://www.cnblogs.com/DaD3zZ-Beyonder/p/5346208.html
Copyright © 2011-2022 走看看