1. 程式人生 > >[ZJOI2006]書架

[ZJOI2006]書架

fine pos 離開 i++ its 基本操作 ret pri build

題目描述

小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

都是splay的基本操作,然而我都調成兒子了2333

總結一下小錯:

1.變量寫混(常規操作)

2.把x插入到第k大後面的時候忘了更新size(也差不多是常規操作了)

3.最致命的是我刪除的時候如果被刪除的元素是最大或者最小的話,我把根設成了前驅(後繼),而不是它們在樹上的兒子2333,這個錯的真心玄學。

所以以後一定要,think twice ,code once.

#include<bits/stdc++.h>
#define ll long long
#define maxn 100005
using namespace std;
int f[maxn],ch[maxn][2];
int a[maxn],siz[maxn];
int n,m,pos,root,lefbig,rigsml;
int cnt,S,T,u,p;
char s[23];

inline void update(int x){
    siz[x]=siz[ch[x][0]]+siz[ch[x][1]]+1;
}

inline int get(int x){
    return ch[f[x]][1]==x;
}

inline void rotate(int x){
    int fa=f[x],ffa=f[fa],tp=get(x);
    ch[fa][tp]=ch[x][tp^1],f[ch[fa][tp]]=fa;
    ch[x][tp^1]=fa,f[fa]=x;
    f[x]=ffa;
    if(ffa) ch[ffa][ch[ffa][1]==fa]=x;
    if(root==fa) root=x;
    
    update(fa),update(x);
}

inline void splay(int x,int d){
    for(int fa;(fa=f[x])!=d;rotate(x))
        if(f[fa]!=d) rotate(get(fa)==get(x)?fa:x);
}

inline int pre(int x){
    x=ch[x][0];
    while(ch[x][1]) x=ch[x][1];
    return x;
}

inline int nxt(int x){
    x=ch[x][1];
    while(ch[x][0]) x=ch[x][0];
    return x;
}

inline void del(int x){
    splay(x,0);
    lefbig=pre(root),rigsml=nxt(root);
    if(!lefbig||!rigsml){
        if(!lefbig&&!rigsml) root=0;
        else if(!lefbig) f[ch[root][1]]=0,root=ch[root][1];
        else f[ch[root][0]]=0,root=ch[root][0];
    }
    else{
        splay(lefbig,0),splay(rigsml,root);
        ch[ch[root][1]][0]=0,update(ch[root][1]),update(root);
    }
    
    siz[x]=f[x]=ch[x][0]=ch[x][1]=0;
}

inline int rank(int x){
    int an=siz[ch[x][0]],fa;
    while(x){
        fa=f[x];
        if(get(x)) an+=siz[ch[fa][0]]+1;
        x=fa;
    }
    return an;
}

inline int BOOK(int x){
    int now=root;
    while(now){
        if(siz[ch[now][0]]>=x) now=ch[now][0];
        else{
            x-=siz[ch[now][0]]+1;
            if(!x) return now;
            now=ch[now][1];
        }
    }
}

inline void ins(int x,int F){
    int now=root,fa=0,las;
    while(now){
    	siz[now]++;
        if(F<=siz[ch[now][0]]) fa=now,now=ch[now][0],las=0;
        else{
            F-=siz[ch[now][0]]+1;
            fa=now,now=ch[now][1];
            las=1;
        }
    }

    siz[x]=1,f[x]=fa,ch[fa][las]=x,update(fa);
    splay(x,0);
}

int build(int l,int r,int fa){
    if(l>r) return 0;
    int mid=l+r>>1,O=a[mid];
    f[O]=fa;
    ch[O][0]=build(l,mid-1,O);
    ch[O][1]=build(mid+1,r,O);
    update(O);
    
    return O;
}

void print(int x){
    if(!x) return;
    print(ch[x][0]);
    printf("%d ",x);
    print(ch[x][1]);
}

int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++) scanf("%d",a+i);
    root=build(1,n,0);
    while(m--){
        scanf("%s",s);
        if(s[0]==‘I‘){
            scanf("%d%d",&S,&T);
            u=rank(S)+T;
            del(S);
            ins(S,u);
        }
        else if(s[0]==‘T‘){
            scanf("%d",&S);
            del(S);
            ins(S,0);
        }
        else if(s[0]==‘B‘){
            scanf("%d",&S);
            del(S);
            ins(S,n-1);
        }
        else if(s[0]==‘A‘){
            scanf("%d",&S);
            printf("%d\n",rank(S));
        }
        else{
            scanf("%d",&S);
            printf("%d\n",BOOK(S));
        }
	//	print(root);
	//	puts("");
    }
    
    return 0;
}

  

[ZJOI2006]書架