1. 程式人生 > >[Zjoi2006]Book書架

[Zjoi2006]Book書架

找到 www. inpu class pla sample ons return 放置

Description
Sally有一個很大的書櫃。這個書櫃的構造有些獨特,即書櫃裏的書是從上至下堆放成一列。她用1到n的正整數給每本書都編了號。Sally在看書的時候,每次取出一本書,看完後放回書櫃然後再拿下一本。由於這些書太有吸引力了,所以她看完後常常會忘記原來是放在書櫃的什麽位置。不過Sally的記憶力是非常好的,所以每次放書的時候至少能夠那本書放在拿出來時的位置附近,比如說她拿的時候這本書上面有X本書,那麽放回去時這本書上面就只可能有X-1、X或X+1本書。當然也有特殊情況,比如在看書的時候突然電話響了或者有朋友來訪。這時候粗心的Sally會隨手把書放在書櫃裏所有書的最上面或者最下面,然後轉身離開。久而久之,Sally的書櫃裏的書的順序就會越來越亂,找到特定的編號的書就變得越來越困難。於是她想請你幫她編寫一個圖書管理程序,處理她看書時的一些操作,以及回答她的兩個提問:(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本書的編號。
n,m<=80000

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

這題多兩個操作,取出最靠右的點和最靠左的點。insert操作把點往左挪或往右挪,Top/Down放到最上面或最下面就好了,具體操作可以看下代碼

關於本人splay代碼操作詳解請參考淺談算法——splay

#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define inf 0x7f7f7f7f
using namespace std;
typedef long long ll;
typedef unsigned int ui;
typedef unsigned long long ull;
inline int read(){
    int x=0,f=1;char ch=getchar();
    for (;ch<‘0‘||ch>‘9‘;ch=getchar())  if (ch==‘-‘)    f=-1;
    for (;ch>=‘0‘&&ch<=‘9‘;ch=getchar())    x=(x<<1)+(x<<3)+ch-‘0‘;
    return x*f;
}
inline void print(int x){
    if (x>=10)     print(x/10);
    putchar(x%10+‘0‘);
}
const int N=8e4;
struct Splay{
    #define T(x) (tree[f[x]][1]==x)
    int tree[N+10][2],f[N+10],size[N+10],val[N+10];
    int root,len;
    void updata(int x){size[x]=size[tree[x][0]]+size[tree[x][1]]+1;}
    void build(int n){
        for (int i=1;i<=n;i++)  val[i]=read();
        for (int i=1;i<n;i++)   f[val[i]]=val[i+1],tree[val[i+1]][0]=val[i],size[val[i]]=i;
        size[root=val[n]]=n;
    }
    void move(int x){
        int fa=f[x],son=tree[x][T(x)^1];
        tree[x][T(x)^1]=fa;
        tree[fa][T(x)]=son;
        if (son)    f[son]=fa;
        f[x]=f[fa];
        if (f[x])   tree[f[x]][T(fa)]=x;
        f[fa]=x;
        updata(fa),updata(x);
    }
    void splay(int x){
        while (f[x]){
            if (f[f[x]])    T(x)==T(f[x])?move(f[x]):move(x);
            move(x);
        }
        root=x;
    }
    int get_pre(){
        int x=tree[root][0];
        while (tree[x][1])  x=tree[x][1];
        return x;
    }
    int get_suc(){
        int x=tree[root][1];
        while (tree[x][0])  x=tree[x][0];
        return x;
    }
    int get_front(){
        int x=root;
        while (tree[x][0])  x=tree[x][0];
        return x;
    }
    int get_last(){
        int x=root;
        while (tree[x][1])  x=tree[x][1];
        return x;
    }
    void Delete(int x){
        splay(x);
        if (!(tree[x][0]&&tree[x][1])){
            f[root=tree[x][0]+tree[x][1]]=0;
            f[x]=tree[x][0]=tree[x][1]=size[x]=0;
            return;
        }
        int i=get_pre();
        splay(i);
        f[tree[i][1]=tree[x][1]]=i;
        f[x]=tree[x][0]=tree[x][1]=size[x]=0;
        updata(i);
    }
    int find(int x,int i){
        if (size[tree[i][0]]+1==x)  return i;
        if (x<=size[tree[i][0]])    return find(x,tree[i][0]);
        return find(x-size[tree[i][0]]-1,tree[i][1]);
    }
    void change(int x,int t){
        Delete(x);
        int i=t?get_last():get_front();
        splay(i);
        f[tree[i][t]=x]=i;
        size[x]++,size[i]++;
    }
    void insert(int x,int t){
        splay(x);
        int i=t?get_suc():get_pre();
        Delete(x);
        splay(i);
        f[tree[x][t]=tree[i][t]]=x;
        f[tree[i][t]=x]=i;
        size[x]=size[tree[x][t]]+1;
        size[i]++;
    }
    void Ask(int x){
        splay(x);
        printf("%d\n",size[tree[x][0]]);
    }
    void query(int x){printf("%d\n",find(x,root));}
}T;
char s[10];
int main(){
    int n=read(),m=read();
    T.build(n);
    for (int i=1;i<=m;i++){
        scanf("%s",s);
        if (s[0]==‘I‘){
            int x=read(),t=read();
            if (t)  T.insert(x,t==1);
        }
        if (s[0]==‘T‘)  T.change(read(),0);
        if (s[0]==‘B‘)  T.change(read(),1);
        if (s[0]==‘A‘)  T.Ask(read());
        if (s[0]==‘Q‘)  T.query(read());
    }
    return 0;
}

[Zjoi2006]Book書架