zoukankan      html  css  js  c++  java
  • bzoj1861 [Zjoi2006]Book 书架

    1861: [Zjoi2006]Book 书架

    Time Limit: 4 Sec  Memory Limit: 64 MB
    Submit: 1988  Solved: 1122
    [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来维护,维护的是“位置”.那么在插入的时候不能按照书的编号进行插入,而是按照书的位置,也就是当前的书是第几小的.这样我们就要维护一个size数组,代表以i为根的子树有多少个节点.因为splay节点记录的是书的编号,并不是次序,所以需要利用size数组来知道当前节点代表的次序是多少.每次将当前要插入的次序与左子节点代表的次序相比较.

              对于前三种操作,其实就是查询+删除+插入的结合体.查询是需要查编号为S的书在splay上节点是哪一个,删除就是将原来的点删掉.并维护一个pos数组,表示编号为S的书在splay上节点是哪一个,进行完每次操作后都要更新pos数组.对于第四个操作,将S旋转到根节点上,那么左子树的大小就是答案.第五个操作则利用size数组不断地缩小范围,最后可以锁定到一个元素上.

              需要关注的是size数组的维护.在每次删除,插入和左右旋都要修改被改变的点的size值.

              数组要开大点,一开始一直RE以为访问到了无效节点......

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    
    using namespace std;
    
    const int maxn = 1000010;
    int n,m,sizee[maxn],pos[maxn],tot,root,a[maxn];
    
    struct node
    {
        int fa,left,right,v;
    } e[maxn];
    
    void update(int x)
    {
        sizee[x] = 1;
        if (e[x].left != -1)
            sizee[x] += sizee[e[x].left];
        if (e[x].right != -1)
            sizee[x] += sizee[e[x].right];
    }
    
    int getsize(int x)
    {
        if (x == -1)
            return 0;
        return sizee[x];
    }
    
    void turnr(int x)
    {
        int y = e[x].fa;
        int z = e[y].fa;
        e[y].left = e[x].right;
        if (e[x].right != -1)
            e[e[x].right].fa = y;
        e[x].fa = z;
        if (z != -1)
        {
            if (e[z].left == y)
                e[z].left = x;
            else
                e[z].right = x;
        }
        e[x].right = y;
        e[y].fa = x;
        update(y);
        update(x);
    }
    
    void turnl(int x)
    {
        int y = e[x].fa;
        int z = e[y].fa;
        e[y].right = e[x].left;
        if (e[x].left != -1)
            e[e[x].left].fa = y;
        e[x].fa = z;
        if (z != -1)
        {
            if (e[z].left == y)
                e[z].left = x;
            else
                e[z].right = x;
        }
        e[x].left = y;
        e[y].fa = x;
        update(y);
        update(x);
    }
    
    void splay(int x)
    {
        while (e[x].fa != -1)
        {
            int y = e[x].fa;
            int z = e[y].fa;
            if (z == -1)
            {
                if (x == e[y].left)
                    turnr(x);
                else
                    turnl(x);
            }
            else
            {
                if (e[z].left == y && e[y].left == x)
                {
                    turnr(y);
                    turnr(x);
                }
                else
                {
                    if (e[z].right == y && e[y].right == x)
                    {
                        turnl(y);
                        turnl(x);
                    }
                    else
                    {
                        if (e[z].left == y && e[y].right == x)
                        {
                            turnl(x);
                            turnr(x);
                        }
                        else
                        {
                            turnr(x);
                            turnl(x);
                        }
                    }
                }
            }
        }
        root = x;
    }
    
    void del(int x)
    {
        splay(x);
        if (e[x].left == -1 && e[x].right == -1)
        {
            root = -1;
            return;
        }
        if (e[x].left == -1)
        {
            root = e[x].right;
            e[e[x].right].fa = -1;
            return;
        }
        if (e[x].right == -1)
        {
            root = e[x].left;
            e[e[x].left].fa = -1;
            return;
        }
        int j = e[x].left;
        while (e[j].right != -1)
            j = e[j].right;
        splay(j);
        e[j].right = e[x].right;
        e[e[x].right].fa = j;
        root = j;
        update(j);
    }
    
    
    void insert(int x,int y,int k)
    {
        if (k == 1 && e[x].left == -1)
        {
            e[x].left = ++tot;
            e[tot].left = e[tot].right = -1;
            e[tot].fa = x;
            e[tot].v = y;
            return;
        }
        if (k == 2 + getsize(e[x].left) && e[x].right == -1)
        {
            e[x].right = ++tot;
            e[tot].left = e[tot].right = -1;
            e[tot].fa = x;
            e[tot].v = y;
            return;
        }
        if (k <= 1 + getsize(e[x].left))
            insert(e[x].left,y,k);
        else
            insert(e[x].right,y,k - 1 - getsize(e[x].left));
        update(x);
    }
    
    int query(int k,int p)
    {
        int x = p;
        while (1)
        {
            if (k == 1 + getsize(e[x].left))
                return x;
            if (k > 1 + getsize(e[x].left))
            {
                k -= 1 + getsize(e[x].left);
                x = e[x].right;
            }
            else
                x = e[x].left;
        }
    }
    
    int query2(int x)
    {
        if (x == -1)
            return 0;
        splay(x);
        return getsize(e[x].left) + 1;
    }
    
    int main()
    {
        scanf("%d%d",&n,&m);
        for (int i = 1; i <= n; i++)
            scanf("%d",&a[i]);
        pos[a[1]] = 1;
        root = ++tot;
        sizee[tot] = 1;
        e[tot].fa = e[tot].left = e[tot].right = -1;
        e[tot].v = a[1];
        for (int i = 2; i <= n; i++)
        {
            pos[a[i]] = i;
            insert(root,a[i],i);
            splay(tot);
        }
        for (int i = 1; i <= m; i++)
        {
            char s[10];
            int x,y;
            scanf("%s",s + 1);
            if (s[1] == 'Q')
            {
                scanf("%d",&x);
                printf("%d
    ",e[query(x,root)].v);
            }
            if (s[1] == 'T')
            {
                scanf("%d",&x);
                del(pos[x]);
                insert(root,x,1);
                pos[x] = tot;
                splay(tot);
            }
            if (s[1] == 'B')
            {
                scanf("%d",&x);
                del(pos[x]);
                insert(root,x,n);
                pos[x] = tot;
                splay(tot);
            }
            if (s[1] == 'A')
            {
                scanf("%d",&x);
                printf("%d
    ",query2(pos[x]) - 1);
            }
            if (s[1] == 'I')
            {
                scanf("%d%d",&x,&y);
                int u = query2(pos[x]);
                del(pos[x]);
                u = u + y;
                insert(root,x,u);
                splay(tot);
                pos[x] = tot;
            }
        }
    
        return 0;
    }
  • 相关阅读:
    windows2008R2新增磁盘处于脱机状态及介质写入受保护解决办法
    Oracle查询字段结果加单引号以及其他内容
    系统部署Oracle及cmd命令
    如何允许谷歌浏览器Adobe Flash Player一直运行
    浏览器被hao123篡改怎么办?
    Oracle数据库备份还原
    11_程序中的循环
    10_选择结构
    09_控制台输入
    08_运算符
  • 原文地址:https://www.cnblogs.com/zbtrs/p/8252217.html
Copyright © 2011-2022 走看看