[bzoj1861][Zjoi2006]Book书架

我写的非常shi,还巨tm慢,不过。。。很好理解qwq

题意:给编号为1~n的书,支持操作:

1.把编号为x的放在第一个

2.放在最后一个

3.上移一个或下移一个或不动

4.询问编号为x的在第几个

5.第x个编号是几

我的方法是一直给每个点一个权值,以权值为关键字维护splay,这样和普通平衡树一样了。所以说好像可以set水过?

要记录编号为x的权值是几。查询直接查,移动时候先删除,再把权值修改成合适的值(第一个就修改成最小值-1,往前一个就修改成前驱和前驱的前驱中间值,类似)。

顺便每个节点维护一下编号就好了。。

#include<bits/stdc++.h>
#define eps 1e-10
using namespace std;
const int N=200010;
typedef double ff;
inline int read(){
    int r=0,f=1,c=getchar();
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){r=r*10+c-'0';c=getchar();}
    return r*f;
}
int ch[N][2],siz[N],fa[N],f[N];
ff pos[N],w[N];
int rt,tot,now;
void pp(int x){
    siz[x]=siz[ch[x][0]]+siz[ch[x][1]]+1;
}
int get(int x){
    return x==ch[fa[x]][1];
}
void rotate(int x){
    int y=fa[x],z=fa[y],px=get(x),py=get(y);
    int t=ch[x][px^1];
    ch[y][px]=t;fa[t]=y;
    ch[x][px^1]=y;fa[y]=x;
    ch[z][py]=x;fa[x]=z;
    pp(y);
}
void splay(int x){
    int y=fa[x];
    while(y){
        if(fa[y])
        rotate(get(x)==get(y)?y:x);
        rotate(x);y=fa[x];
    }
    pp(x);rt=x;
}
ff minn(){
    int x=rt;
    while(ch[x][0])x=ch[x][0];
    return w[x];
}
ff maxx(){
    int x=rt;
    while(ch[x][1])x=ch[x][1];
    return w[x];
}
int pre(){
    int x=ch[rt][0];
    while(ch[x][1])x=ch[x][1];
    return x;
}
int nxt(){
    int x=ch[rt][1];
    while(ch[x][0])x=ch[x][0];
    return x;
}
int qnum(int rk){
    int x=rt;
    while(1){
        int y=ch[x][0];
        if(y&&siz[y]>=rk)x=y;
        else{
            rk-=(y?siz[y]:0)+1;
            if(rk<=0){
                splay(x);return f[x];
            }
            x=ch[x][1];
        }
    }
}
int qrank(ff val){
    int x=rt;
    while(abs(w[x]-val)>eps)
    x=ch[x][val>w[x]];
    splay(x);
    return siz[ch[x][0]];
}
void ins(ff val){
    if(!rt){
        rt=++tot;w[tot]=val;
        siz[tot]=1;f[tot]=now;
        return;
    }
    int x=rt;
    while(1){
        int y=ch[x][0];
        y=x,x=ch[x][val>w[x]];
        if(!x){
            w[++tot]=val;
            ch[y][val>w[y]]=tot;fa[tot]=y;
            siz[tot]=1;f[tot]=now;splay(tot);
            return;
        }
    }
}
void del(ff val){
    qrank(val);
    if(!ch[rt][0]&&!ch[rt][1]){
        rt=0;return;
    }
    int x=-1;
    x=ch[rt][0]?x:1;
    x=ch[rt][1]?x:0;
    if(~x){
        rt=ch[rt][x];fa[rt]=0;
        return;
    }
    x=ch[rt][1];
    splay(pre());
    ch[rt][1]=x,fa[x]=rt;
    pp(rt);
}
void dfs(int x){
    if(!x)return;
    dfs(ch[x][0]);
    printf("%.0f ",w[x]);
    dfs(ch[x][1]);
}
int main(){
    int n=read(),m=read();
    for(int i=1;i<=n;i++)
    now=read(),ins(i*1000),pos[now]=i*1000;
    while(m--){
        char s[10];scanf("%s",s);
        if(s[0]=='T'){
            int x=read(),y=minn();
            del(pos[x]);
            now=x;ins(y-1000);
            pos[x]=y-1000;
        }
        else if(s[0]=='B'){
            int x=read(),y=maxx();
            del(pos[x]);
            now=x;ins(y+1000);
            pos[x]=y+1000;
        }
        else if(s[0]=='I'){
            int x=read(),o=read();
            if(!o)continue;
            ff t=pos[x],v;int y,z;
            if(~o){
                qrank(t);int y=pre();
                if(abs(w[y]-minn())>eps){
                    splay(y);z=pre();
                    v=(w[y]+w[z])/2;
                }
                else v=w[y]-1000;
                pos[x]=v;now=x;ins(v);
            }
            else{
                qrank(t);int y=nxt();
                if(abs(w[y]-maxx())>eps){
                    splay(y);z=nxt();
                    v=(w[y]+w[z])/2;
                }
                else v=w[y]+1000;
                pos[x]=v;now=x;ins(v);
            }
        }
        else if(s[0]=='A'){
            printf("%d\n",qrank(pos[read()]));
        }
        else{
            printf("%d\n",qnum(read()));
        }
    }
}
/*
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
*/
View Code

想了想真的可以set水掉= =

posted @ 2018-01-02 14:30  orzzz  阅读(288)  评论(0编辑  收藏  举报