zoukankan      html  css  js  c++  java
  • P2596 [ZJOI2006]书架

    题目描述

    小T有一个很大的书柜。这个书柜的构造有些独特,即书柜里的书是从上至下堆放成一列。她用1到n的正整数给每本书都编了号。

    小T在看书的时候,每次取出一本书,看完后放回书柜然后再拿下一本。由于这些书太有吸引力了,所以她看完后常常会忘记原来是放在书柜的什么位置。不过小T的记忆力是非常好的,所以每次放书的时候至少能够将那本书放在拿出来时的位置附近,比如说她拿的时候这本书上面有X本书,那么放回去时这本书上面就只可能有X-1、X或X+1本书。

    当然也有特殊情况,比如在看书的时候突然电话响了或者有朋友来访。这时候粗心的小T会随手把书放在书柜里所有书的最上面或者最下面,然后转身离开。

    久而久之,小T的书柜里的书的顺序就会越来越乱,找到特定的编号的书就变得越来越困难。于是她想请你帮她编写一个图书管理程序,处理她看书时的一些操作,以及回答她的两个提问:(1)编号为X的书在书柜的什么位置;(2)从上到下第i本书的编号是多少。

    输入输出格式

    输入格式:

    第一行有两个数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本书的编号。

    输出格式:

    对于每一条Ask或Query语句你应该输出一行,一个数,代表询问的答案。

    输入输出样例

    输入样例#1:
    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
    输出样例#1:
    2
    9
    9
    7
    5
    3

    说明

    100%的数据,n,m <= 80000

    代码

    虚拟一个节点高度,把高度作为数列进行维护

    T:删除编号为S的书,插入一个虚拟高度为当前最小且编号为S的书

    B:同T,插入虚拟高度为当前最大

    I:交换前驱或后继的信息

    A:查询rank

    Q:查询kth

    #include<bits/stdc++.h>
    #define inf 0x3f3f3f3f
    using namespace std;
    const int maxn=1000000+100;
    int ch[maxn][2],fa[maxn],size[maxn],cnt[maxn],id[maxn],val[maxn],pos[maxn];
    char op[10];
    //表示节点编号,val表示节点虚拟高度,pos表id所在位置 
    int root,ncnt;
    int mi,mx;
    inline int read()
    {
        int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
        return x*f;
    }
    void output(int u=root)
    {
        if(ch[u][0])output(ch[u][0]);
        if(val[u]==inf||val[u]==-inf)return;
        printf("%d ",id[u]);
        if(ch[u][1])output(ch[u][1]);
    }
    void pushup(int u)
    {
        size[u]=size[ch[u][0]]+size[ch[u][1]]+cnt[u];
    }
    int chk(int u)
    {
        return ch[fa[u]][1]==u;
    }
    void rotate(int u)
    {
        int f=fa[u],ff=fa[f],k=chk(u),s=ch[u][k^1];
        ch[f][k]=s,fa[s]=f;
        ch[ff][chk(f)]=u,fa[u]=ff;
        ch[u][k^1]=f,fa[f]=u;
        pushup(u),pushup(f);
    }
    void splay(int u,int goal=0)
    {
        while(fa[u]!=goal)
        {
            int f=fa[u],ff=fa[f];
            if(ff!=goal)
            {
                if(chk(u)==chk(f))rotate(f);
                else rotate(u);
            }
            rotate(u);
        }
        if(!goal)root=u;
    }
    void insert(int x,int y)
    {
        int u=root,f=0;
        while(u&&val[u]!=x)
        f=u,u=ch[u][x>val[u]];
        u=++ncnt;
        if(f)ch[f][x>val[f]]=u;
        fa[u]=f,val[u]=x,id[u]=y,pos[y]=u;
        size[u]=cnt[u]=1;
        ch[u][0]=ch[u][1]=0;
        splay(u);
    } 
    int kth(int k)
    {
        int u=root;
        while(1)
        {
            if(ch[u][0]&&k<=size[ch[u][0]])
            u=ch[u][0];
            else if(k>size[ch[u][0]]+cnt[u])
            k-=size[ch[u][0]]+cnt[u],u=ch[u][1];
            else return u; 
        }
    }
    int ask(int x)
    {
        splay(pos[x]);
        return size[ch[root][0]]-1;
    }
    int pre(int u)
    {
        splay(u);
        u=ch[root][0];
        while(ch[u][1])u=ch[u][1];
        return u;
    }
    int succ(int u)
    {
        splay(u);
        u=ch[root][1];
        while(ch[u][0])u=ch[u][0];
        return u;
    }
    void remove(int u)
    {
        int last=pre(u),next=succ(u);
        splay(last),splay(next,last);
        ch[next][0]=0;
    }
    void top(int s)
    {
        remove(pos[s]);
        insert(--mi,s);
    }
    void bottom(int s)
    {
        remove(pos[s]);
        insert(++mx,s);
    }
    void change(int u,int o)
    {
        int now=pos[u];
        if(o==1)
        {
            int next=succ(now);
            if(!id[next])return;
            pos[u]=next,pos[id[next]]=now;
            swap(id[now],id[next]);
        }
        if(o==-1)
        {
            int last=pre(now);
            if(!id[last])return;
            pos[u]=last,pos[id[last]]=now;
            swap(id[now],id[last]);
        } 
    }
    
    int main()
    {
        insert(inf,0),insert(-inf,0);
        int n=read(),m=read();
        mi=0,mx=n+1;
        for(int i=1;i<=n;i++)
        insert(i,read());
        for(int i=1;i<=m;i++)
        {
            cin>>op;
            if(op[0]=='T'){int x=read();top(x);}
            if(op[0]=='B'){int x=read();bottom(x);}
            if(op[0]=='I'){int x=read(),y=read();change(x,y);}
            if(op[0]=='A'){int x=read();printf("%d
    ",ask(x));}
            if(op[0]=='Q'){int x=read();printf("%d
    ",id[kth(x+1)]);} 
        }
        return 0;
    }
    View Code
  • 相关阅读:
    塔 · 第 二 条 约 定
    nyoj 325
    塔 · 第 一 条 约 定
    大一上
    Django之ORM
    mysql概念
    数据库索引
    使用pymysql进行数据库的增删改查
    sql注入攻击
    pymysql
  • 原文地址:https://www.cnblogs.com/DriverBen/p/10916058.html
Copyright © 2011-2022 走看看