1861: [Zjoi2006]Book 书架

来源:互联网 发布:九仙图仙羽进阶数据 编辑:程序博客网 时间:2024/05/02 01:20

1861: [Zjoi2006]Book 书架

Time Limit: 4 Sec  Memory Limit: 64 MB
Submit: 1822  Solved: 1038
[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


这一道题卡了五天!!!!!!

#include<cstring>#include<cstdio>#include<algorithm>using namespace std;#define MAXN 100000struct Spaly{    int ch[MAXN][2],f[MAXN],size[MAXN],cnt[MAXN],key[MAXN],rank[MAXN],val[MAXN];    int sz,root;    void init()    {        sz=root=0;    }    inline void clear(int x)    {        ch[x][0]=ch[x][1]=f[x]=size[x]=cnt[x]=key[x]=0;    }    inline bool get(int x)    {        return ch[f[x]][1]==x;    }    inline void update(int x)    {        if (x)        {            size[x]=cnt[x];            if (ch[x][0]) size[x]+=size[ch[x][0]];            if (ch[x][1]) size[x]+=size[ch[x][1]];        }    }    inline void rotate(int x)    {        int old=f[x],oldf=f[old],whichx=get(x);        ch[old][whichx]=ch[x][whichx^1];        f[ch[old][whichx]]=old;        ch[x][whichx^1]=old;        f[old]=x;        f[x]=oldf;        if (oldf)            ch[oldf][ch[oldf][1]==old]=x;        update(old);        update(x);    }    inline void splay(int x)    {        for (int fa; fa=f[x]; rotate(x))            if (f[fa])                rotate((get(x)==get(fa))?fa:x);        root=x;    }    inline void insert(int x)    {        if (root==0)        {            sz++;            ch[sz][0]=ch[sz][1]=f[sz]=0;            root=sz;            size[sz]=cnt[sz]=1;            key[sz]=x;            return;        }        int now=root,fa=0;        while(1)        {            if (x==key[now])            {                cnt[now]++;                update(now);                update(fa);                splay(now);                break;            }            fa=now;            now=ch[now][key[now]<x];            if (now==0)            {                sz++;                ch[sz][0]=ch[sz][1]=0;                f[sz]=fa;                size[sz]=cnt[sz]=1;                ch[fa][key[fa]<x]=sz;                key[sz]=x;                update(fa);                splay(sz);                break;            }        }    }    inline int find(int x)///x是第几名    {        int now=root,ans=0;        while(1)        {            if (x<key[now])                now=ch[now][0];            else            {                ans+=(ch[now][0]?size[ch[now][0]]:0);                if (x==key[now])                {                    splay(now);                    return ans+1;                }                ans+=cnt[now];                now=ch[now][1];            }        }    }    inline int findx(int x)///第x名是谁    {        int now=root;        while(1)        {            if (ch[now][0]&&x<=size[ch[now][0]])                now=ch[now][0];            else            {                int temp=(ch[now][0]?size[ch[now][0]]:0)+cnt[now];                if (x<=temp) return key[now];                x-=temp;                now=ch[now][1];            }        }    }    inline int pre()    {        int now=ch[root][0];        while (ch[now][1]) now=ch[now][1];        return now;    }    inline int next()    {        int now=ch[root][1];        while (ch[now][0]) now=ch[now][0];        return now;    }    inline void del(int x)    {        int whatever=find(x);        if (cnt[root]>1)        {            cnt[root]--;            update(root);            return;        }        if (!ch[root][0]&&!ch[root][1])        {            clear(root);            root=0;            return;        }        if (!ch[root][0])        {            int oldroot=root;            root=ch[root][1];            f[root]=0;            clear(oldroot);            return;        }        else if (!ch[root][1])        {            int oldroot=root;            root=ch[root][0];            f[root]=0;            clear(oldroot);            return;        }        int leftbig=pre(),oldroot=root;        splay(leftbig);        ch[root][1]=ch[oldroot][1];        f[ch[oldroot][1]]=root;        clear(oldroot);        update(root);    }} sp;int main(){    int n,m;    char op[50];    while(scanf("%d%d",&n,&m)!=EOF)    {        sp.init();        for(int i=1; i<=n; i++)        {            int tmp;            scanf("%d",&tmp);            sp.rank[tmp]=i;            sp.val[i]=tmp;            sp.insert(i);        }        while(m--)        {            int cho,ch;            scanf("%s %d",op,&ch);            switch(op[0])            {            case 'T':            {                sp.splay(ch=sp.rank[ch]);                int left=sp.ch[sp.root][0];                if(left==0)                    break;                if(sp.ch[sp.root][1]==0)                {                    sp.ch[sp.root][0]=0;                    sp.ch[sp.root][1]=left;                    break;                }                int pos=sp.next();                sp.ch[pos][0]=left;                sp.f[left]=pos;                sp.ch[sp.root][0]=0;                sp.splay(left);            }            break;            case 'B':            {                sp.splay(ch=sp.rank[ch]);                int right=sp.ch[sp.root][1];                if(right==0)                    break;                if(sp.ch[sp.root][0]==0)                {                    sp.ch[sp.root][1]=0;                    sp.ch[sp.root][0]=right;                    break;                }                int pos=sp.pre();                sp.ch[pos][1]=right;                sp.f[right]=pos;                sp.ch[sp.root][1]=0;                sp.splay(right);            }            break;            case 'A':            {                sp.splay(sp.rank[ch]);                printf("%d\n",sp.size[sp.ch[sp.root][0]]);            }            break;            case 'I':            {                scanf("%d",&cho);                if(cho==0)                    break;                int s;                sp.splay(s=sp.rank[ch]);                int pre=sp.pre();                int net=sp.next();                if(cho==1)///右边                {                    swap(sp.rank[ch],sp.rank[sp.val[net]]);                    swap(sp.val[s],sp.val[net]);                }                else                {                    swap(sp.rank[ch],sp.rank[sp.val[pre]]);                    swap(sp.val[s],sp.val[pre]);                }            }            break;            case 'Q':            {                printf("%d\n",sp.val[sp.findx(ch)]);            }            break;            }        }    }    return 0;}


原创粉丝点击