码迷,mamicode.com
首页 > 其他好文 > 详细

[BZOJ1861][ZJOI2006]书架

时间:2018-01-02 11:37:44      阅读:191      评论:0      收藏:0      [点我收藏+]

标签:play   ==   细节   rip   return   geo   ret   desc   语句   

BZOJ
Luogu
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

sol

就是splay板子题呀(然而还是调了我将近两个小时)
操作1,2注意判本来就是Top或是Bottom的情况
操作3注意交换splay树上的两个节点的时候会涉及很多东西的变动,最好画个图仔细想一想,然后要PUSHUP!(我就是这里WA的)
操作4,5应该是最简单的,就不讲了
练细节的好题吧

code

#include<cstdio>
#include<algorithm>
using namespace std;
const int N = 100005;
int n,m,fa[N],ls[N],rs[N],sz[N],a[N],root;
char s[N];
int gi()
{
    int x=0,w=1;char ch=getchar();
    while ((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
    if (ch=='-') w=0,ch=getchar();
    while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
    return w?x:-x;
}
void pushup(int x){sz[x]=sz[ls[x]]+sz[rs[x]]+1;}
void R_rotate(int x)
{
    int y=fa[x],z=fa[y];
    ls[y]=rs[x];
    if (rs[x]) fa[rs[x]]=y;
    fa[x]=z;
    if (z) if (y==ls[z]) ls[z]=x;else rs[z]=x;
    rs[x]=y;fa[y]=x;
    pushup(y);
}
void L_rotate(int x)
{
    int y=fa[x],z=fa[y];
    rs[y]=ls[x];
    if (ls[x]) fa[ls[x]]=y;
    fa[x]=z;
    if (z) if (y==ls[z]) ls[z]=x;else rs[z]=x;
    ls[x]=y;fa[y]=x;
    pushup(y);
}
void splay(int x,int goal)
{
    while (fa[x]!=goal)
    {
        int y=fa[x],z=fa[y];
        if (z==goal)
            if (x==ls[y]) R_rotate(x);
            else L_rotate(x);
        else
            if (y==ls[z])
                if (x==ls[y]) R_rotate(y),R_rotate(x);
                else L_rotate(x),R_rotate(x);
            else
                if (x==ls[y]) R_rotate(x),L_rotate(x);
                else L_rotate(y),L_rotate(x);
    }
    pushup(x);
    if (!goal) root=x;
}
void Top()
{
    int x=gi();
    splay(x,0);
    if (!ls[x]) return;
    int y=ls[x];
    while (rs[y]) y=rs[y];
    splay(y,x);
    rs[y]=rs[x];if (rs[y]) fa[rs[y]]=y;
    fa[root=y]=0;pushup(y);
    while (ls[y]) y=ls[y];
    ls[y]=x;fa[x]=y;ls[x]=rs[x]=0;sz[x]=1;
    splay(x,0);
}
void Bottom()
{
    int x=gi();
    splay(x,0);
    if (!rs[x]) return;
    int y=rs[x];
    while (ls[y]) y=ls[y];
    splay(y,x);
    ls[y]=ls[x];if (ls[y]) fa[ls[y]]=y;
    fa[root=y]=0;pushup(y);
    while (rs[y]) y=rs[y];
    rs[y]=x;fa[x]=y;ls[x]=rs[x]=0;sz[x]=1;
    splay(x,0);
}
void Insert()
{
    int x=gi(),t=gi();
    splay(x,0);
    if (t==1)
    {
        int y=rs[x];
        while (ls[y]) y=ls[y];
        splay(y,x);
        swap(ls[x],ls[y]);if (ls[x]) fa[ls[x]]=x;if (ls[y]) fa[ls[y]]=y;
        rs[x]=rs[y];if (rs[x]) fa[rs[x]]=x;
        rs[y]=x;fa[x]=y;
        fa[root=y]=0;
        pushup(x);pushup(y);
    }
    if (t==-1)
    {
        int y=ls[x];
        while (rs[y]) y=rs[y];
        splay(y,x);
        swap(rs[x],rs[y]);if (rs[x]) fa[rs[x]]=x;if (rs[y]) fa[rs[y]]=y;
        ls[x]=ls[y];if (ls[x]) fa[ls[x]]=x;
        ls[y]=x;fa[x]=y;
        fa[root=y]=0;
        pushup(x);pushup(y);
    }
}
void Ask()
{
    int x=gi();
    splay(x,0);
    printf("%d\n",sz[ls[x]]);
}
void Query()
{
    int k=gi(),x=root;
    while (233)
    {
        if (k<=sz[ls[x]]) x=ls[x];
        else if (k==sz[ls[x]]+1) break;
        else k-=sz[ls[x]]+1,x=rs[x];
    }
    printf("%d\n",x);
}
int Build(int l,int r,int ff)
{
    if (l>r) return 0;
    int mid=l+r>>1;
    fa[a[mid]]=ff;
    ls[a[mid]]=Build(l,mid-1,a[mid]);
    rs[a[mid]]=Build(mid+1,r,a[mid]);
    pushup(a[mid]);
    return a[mid];
}
int main()
{
    n=gi();m=gi();
    for (int i=1;i<=n;i++)
        a[i]=gi();
    root=Build(1,n,0);
    while (m--)
    {
        scanf("%s",s);
        if (s[0]=='T') Top();
        if (s[0]=='B') Bottom();
        if (s[0]=='I') Insert();
        if (s[0]=='A') Ask();
        if (s[0]=='Q') Query();
    }
    return 0;
}

[BZOJ1861][ZJOI2006]书架

标签:play   ==   细节   rip   return   geo   ret   desc   语句   

原文地址:https://www.cnblogs.com/zhoushuyu/p/8175810.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!