zoukankan      html  css  js  c++  java
  • [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
    ",qrank(pos[read()]));
            }
            else{
                printf("%d
    ",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水掉= =

  • 相关阅读:
    抽象代数学习笔记
    WC2021 游记
    简单的数学题
    前缀和公式
    杜教筛
    [模板]BZOJ4756线段树合并
    SPOJ 694
    bzoj1367 可并堆
    莫比乌斯反演(理论)
    es6 Set数据结构
  • 原文地址:https://www.cnblogs.com/orzzz/p/8177072.html
Copyright © 2011-2022 走看看