zoukankan      html  css  js  c++  java
  • 【Luogu】P2596书架(Splay)

      题目链接

      通过这题我加深了对Splay的理解,原来Splay的子树也是可以接来接去接到别的点上的,而不是只能旋转qwq

      具体接的办法就是swap大法。

      对于Top操作我们把当前节点Splay到根,然后把它的左子树接到后继上。

      Bottom同理

      对于Insert,暴力swap当前节点和它的前驱或者后继。

      Ask操作就把节点Splay到根,然后输出它的左子树有多少节点。

      Query直接查就行。

      

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cctype>
    #include<cstdlib>
    #define maxn 1000010
    inline long long read(){
        long long num=0,f=1;
        char ch=getchar();
        while(!isdigit(ch)){
            if(ch=='-')    f=-1;
            ch=getchar();
        }
        while(isdigit(ch)){
            num=num*10+ch-'0';
            ch=getchar();
        }
        return num*f;
    }
    
    int pos[maxn];
    int CNT=0;
    struct Splay{
        struct Node{
            int key,val,fa,e[2],size;
        }tree[maxn];
        int tag[maxn];
        int point,tot,root;
        Splay(){point=tot=root=0;memset(tag,0,sizeof(tag));    }
        inline void update(int x){    tree[x].size=tree[tree[x].e[0]].size+tree[tree[x].e[1]].size+1;    }
        inline void connect(int x,int fa,int how){    tree[x].fa=fa;    tree[fa].e[how]=x;    }
        inline int iden(int x){    return x==tree[tree[x].fa].e[1];    }
        inline void rotate(int x){
            int y=tree[x].fa;int r=tree[y].fa;
            if(y==root)    root=x;
            int sony=iden(x);int sonr=iden(y);
            int b=tree[x].e[sony^1];
            connect(b,y,sony);
            connect(y,x,sony^1);
            connect(x,r,sonr);
            update(y);    update(x);
        }
        void splay(int pos,int to){
            to=tree[to].fa;
            while(tree[pos].fa!=to){
                if(tree[tree[pos].fa].fa==to)    rotate(pos);
                else
                    if(iden(pos)==iden(tree[pos].fa)){
                        rotate(tree[pos].fa);
                        rotate(pos);
                    }
                    else{    rotate(pos);    rotate(pos);    }
            }
        }
        int create(int key,int val,int fa){
            tree[++tot].val=val;    tree[tot].fa=fa;
            tree[tot].size=1;    tree[tot].key=key;
            return tot;
        }
        int build(int key,int val){
            if(root==0){    root=create(key,val,0);    return root;    }
            int now=root;
            while(1){
                tree[now].size++;
                int nxt=tree[now].key>key?0:1;
                if(tree[now].e[nxt]==0){
                    connect(create(key,val,now),now,nxt);
                    return tot;
                }
                now=tree[now].e[nxt];
            }
        }
        void insert(int key,int val){
            int p=build(key,val);
            pos[val]=p;
            if(++CNT=50){
                CNT=0;
                splay(p,root);
            }
        }
        int find(int rnk){
            int now=root;
            while(now){
                if(tree[tree[now].e[0]].size+1==rnk)    return now;
                else if(tree[tree[now].e[0]].size>=rnk)    now=tree[now].e[0];
                else{
                    rnk-=tree[tree[now].e[0]].size+1;
                    now=tree[now].e[1];
                }
            }
        }
        void rotop(int val){
            val=pos[val];
            splay(val,root);
            int le=tree[val].e[0];
            if(le==0)    return;
            if(tree[val].e[1]==0){
                connect(le,val,1);
                tree[val].e[0]=0;
                update(val);
            }
            else{
                int deal=find(tree[tree[val].e[0]].size+2);
                connect(tree[val].e[0],deal,0);    tree[val].e[0]=0;
                int now=deal;
                while(now){
                    update(now);
                    now=tree[now].fa;
                }
                splay(deal,root);
            }
        }
        void roend(int val){
            val=pos[val];
            splay(val,root);
            int ri=tree[val].e[1];
            if(ri==0)    return;
            if(tree[val].e[0]==0){
                connect(ri,val,0);
                tree[val].e[1]=0;
                update(val);
            }
            else{
                int deal=find(tree[tree[val].e[0]].size);
                connect(tree[val].e[1],deal,1);    tree[val].e[1]=0;
                int now=deal;
                while(now){
                    update(now);
                    now=tree[now].fa;
                }
                splay(deal,root);
            }
        }
        void rofro(int val){
            val=pos[val];
            splay(val,root);
            int deal=find(tree[tree[val].e[0]].size);
            std::swap(pos[tree[val].val],pos[tree[deal].val]);
            std::swap(tree[val].val,tree[deal].val);
        }
        void rosub(int val){
            val=pos[val];
            splay(val,root);
            int deal=find(tree[tree[val].e[0]].size+2);
            std::swap(pos[tree[val].val],pos[tree[deal].val]);
            std::swap(tree[val].val,tree[deal].val);
        }
        int rank(int key){
            int now=root;
            while(now){
                if(tree[tree[now].e[0]].size+1==key)    return tree[now].val;
                if(tree[tree[now].e[0]].size>=key)    now=tree[now].e[0];
                else{
                    key-=tree[tree[now].e[0]].size+1;
                    now=tree[now].e[1];
                }
            }
            return 0;
        }
        int arank(int val){
            val=pos[val];
            splay(val,root);
            return tree[tree[val].e[0]].size;
        }
    }s;
    
    int main(){
        int n=read(),m=read();
        for(int i=1;i<=n;++i){
            int x=read();
            s.insert(i,x);
        }
        for(int i=1;i<=m;++i){
            char c[10];int x;
            scanf("%s%d",c,&x);
            switch(c[0]){
                case 'T':{
                    s.rotop(x);
                    break;
                }
                case 'B':{
                    s.roend(x);
                    break;
                }
                case 'I':{
                    int y=read();
                    if(y==-1)    s.rofro(x);
                    if(y==1)    s.rosub(x);
                    break;
                }
                case 'A':{
                    printf("%d
    ",s.arank(x));
                    break;
                }
                case 'Q':{
                    printf("%d
    ",s.rank(x));
                    break;
                }
            }
        }
        return 0;
    }
  • 相关阅读:
    hdu 3951 Coin Game
    hdu 1273 漫步森林
    hdu 2082 找单词
    kmp算法(模板)
    CodeForces 742B Arpa’s obvious problem and Mehrdad’s terrible solution
    大二上每日总结
    大二上每日总结
    大二上每日总结
    大二上学期周总结
    大二上每日总结
  • 原文地址:https://www.cnblogs.com/cellular-automaton/p/8298570.html
Copyright © 2011-2022 走看看