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\n",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\n",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;
}

 

 

 

posted @ 2018-01-09 18:17  zbtrs  阅读(179)  评论(0编辑  收藏  举报