BZOJ1861: [Zjoi2006]Book 书架

Posted mt-li

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ1861: [Zjoi2006]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
 
 
我的splay还只停留在模板题的阶段上,这垃圾题我写了1.5小时
真丢人,我只能生套模板,设a数组:a[i]表示i编号的数在第几位
一开始我们给他的编号+max(n,m)
在定义l,r
那么我们top就在a[s]=max(n,m)-(++l)
bottom就在a[s]=max(n,m)+n+(++r)
然后就过了
 
我真菜
 
代码如下:
#include<cmath>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
using namespace std;
struct node{
    int c,d,f,id,son[2];
}tr[2100000];int len,root;
int a[250000];int l,r;
void update(int x)
{
    int lc=tr[x].son[0],rc=tr[x].son[1];
    tr[x].c=tr[lc].c+tr[rc].c+1;
}
void add(int d,int id,int f)
{
    len++;
    tr[len].d=d;tr[len].f=f;tr[len].id=id;tr[len].c=1;
    if(d<tr[f].d)tr[f].son[0]=len;
    else tr[f].son[1]=len;
}
void rotate(int x,int w)
{
    int f=tr[x].f,ff=tr[f].f;
    int r,R;
    
    r=tr[x].son[w],R=f;
    tr[R].son[1-w]=r;
    if(r!=0)tr[r].f=R;
    
    r=x,R=ff;
    if(tr[R].son[0]==f)tr[R].son[0]=r;
    else tr[R].son[1]=r;
    tr[r].f=R;
    
    r=f,R=x;
    tr[r].f=R;
    tr[R].son[w]=r;
    
    update(f);
    update(x);
}
void splay(int x,int rt)
{
    while(tr[x].f!=rt)
    {
        int f=tr[x].f,ff=tr[f].f;
        if(ff==rt)
        {
            if(tr[f].son[0]==x)rotate(x,1);
            else rotate(x,0);
        }
        else
        {
                 if(tr[ff].son[0]==f&&tr[f].son[0]==x){rotate(f,1);rotate(x,1);}
            else if(tr[ff].son[0]==f&&tr[f].son[1]==x){rotate(x,0);rotate(x,1);}
            else if(tr[ff].son[1]==f&&tr[f].son[0]==x){rotate(x,1);rotate(x,0);}
            else if(tr[ff].son[1]==f&&tr[f].son[1]==x){rotate(f,0);rotate(x,0);}
        }
    }
    if(rt==0)root=x;
}
int findip(int d)
{
    int x=root;
    while(tr[x].d!=d)
    {
        if(d<tr[x].d)
        {
            if(tr[x].son[0]==0)break;
            x=tr[x].son[0];
        }
        else
        {
            if(tr[x].son[1]==0)break;
            x=tr[x].son[1];
        }
    }
    return x;
}
void ins(int d,int id)
{
    if(root==0){add(d,id,0);root=len;return ;}
    int x=findip(d);
    add(d,id,x);
    update(x);
    splay(len,0);
}
void del(int d)
{
    int x=findip(d);splay(x,0); 
    if(tr[x].son[0]==0&&tr[x].son[1]==0){root=0;len=0;}
    else if(tr[x].son[0]==0&&tr[x].son[1]!=0){root=tr[x].son[1];tr[root].f=0;}
    else if(tr[x].son[0]!=0&&tr[x].son[1]==0){root=tr[x].son[0];tr[root].f=0;}
    else
    {
        int p=tr[x].son[0];
        while(tr[p].son[1]!=0)p=tr[p].son[1];
        splay(p,x);
        int r=tr[x].son[1],R=p;
        tr[R].son[1]=r;
        tr[r].f=R;
        root=R;tr[root].f=0;
        update(R);
    }
}
int findpaiming(int d)
{
    int x=findip(d);splay(x,0);
    return tr[tr[x].son[0]].c;
}
int findshuzi(int k)
{
    int x=root;
    while(1)
    {
        int lc=tr[x].son[0],rc=tr[x].son[1];
        if(k<=tr[lc].c)x=lc;
        else if(k>tr[lc].c+1){k-=tr[lc].c+1;x=rc;}
        else break;
    }
    splay(x,0);
    return tr[x].id;
}
int findqianqu(int d)
{
    int x=findip(d);splay(x,0);
    while(d<=tr[x].d&&tr[x].son[0]!=0)
    {
        x=tr[x].son[0];
        while(tr[x].son[1]!=0)x=tr[x].son[1];
    }
    if(d<=tr[x].d)x=0;
    return tr[x].id;
}
int findhouji(int d)
{
    int x=findip(d);splay(x,0);
    while(d>=tr[x].d&&tr[x].son[1]!=0)
    {
        x=tr[x].son[1];
        while(tr[x].son[0]!=0)x=tr[x].son[0];
    }
    if(d>=tr[x].d)x=0;
    return tr[x].id;
}
int n,m;
int main()
{
    l=r=root=0;
    int nm;
    scanf("%d%d",&n,&m);len=0;nm=max(n,m);
    for(int i=1;i<=n;i++)
    {
        int x;
        scanf("%d",&x);
        a[x]=i+nm;
        ins(i+nm,x);
    }
    char st[51];
    while(m--)
    {
        int s,t;
        scanf("%s",st+1);
        if(st[1]==T)
        {
            scanf("%d",&s);del(a[s]);
            a[s]=nm-(++l);
            ins(a[s],s);
        }
        if(st[1]==B)
        {
            scanf("%d",&s);del(a[s]);
            a[s]=nm+n+(++r);
            ins(a[s],s);
        }
        if(st[1]==I)
        {
            scanf("%d%d",&s,&t);
            if(t==0)continue;
            if(t==1)
            {
                int x=findhouji(a[s]);
                del(a[x]),del(a[s]);
                swap(a[x],a[s]);
                ins(a[x],x);ins(a[s],s);
            }
            else
            {
                int x=findqianqu(a[s]);
                del(a[x]),del(a[s]);
                swap(a[x],a[s]);
                ins(a[x],x);ins(a[s],s);
            }
        }
        if(st[1]==A)
        {
            scanf("%d",&s);
            printf("%d\n",findpaiming(a[s]));
        }
        if(st[1]==Q)
        {
            scanf("%d",&s);
            printf("%d\n",findshuzi(s));
        }
    }
    return 0;
} 

by_lmy

以上是关于BZOJ1861: [Zjoi2006]Book 书架的主要内容,如果未能解决你的问题,请参考以下文章

[BZOJ1861][Zjoi2006]Book 书架

[bzoj1861][Zjoi2006]Book 书架_非旋转Treap

BZOJ 1861: [Zjoi2006]Book 书架 splay

BZOJ1861 [Zjoi2006]Book 书架

bzoj1861: [Zjoi2006]Book 书架

BZOJ 1861 [Zjoi2006]Book 书架 ——Splay