• BZOJ1861 [Zjoi2006]Book 书架 [平衡树]


    书架

    题目描述见链接 .


    color{grey}{最初想法}

    使用SplaySplay维护


    Input: 依次插入节点, 不断 初始插入 到上个节点的右子树中


    Top : 将权值为SS的点 删去 , 再插入作为到SplaySplay的最左边儿子的左儿子


    Bottom : 将权值为SS的点 删去 , 在插入作为SplaySplay的最右边儿子的右儿子


    Insert : 将权值为SS的点 删去 , 设删去的点等级为xx, 将等级为x+T1x+T-1的点SplaySplay到根节点, 把SS插入之间 根节点 (不要在意语序…)


    Ask : 直接将SS节点SplaySplay到根节点, 输出左子树大小即可


    Query : 查询第SS大的元素


    初始插入 : 不断将当前节点插入到 上个插入节点 的右子树即可, 不要忘记Splay到根节点
    删去 : 直接前缀后缀删除法即可
    插入之间 : 将该节点的未来parpar的右儿子置为该节点, 该节点的右儿子置为parpar原来的右儿子


    color{red}{正解部分}

    初始化序列 时不断将第 ii 个元素插入作为第 i1i-1 个元素的右子树 .

    • TopTop 操作: 直接将 ii 元素旋转到根节点, 将其左子树变为 ii后继 的左儿子 .
    • BottomBottom 操作: 直接将 ii 元素旋转到根节点, 将其右子树变为 ii前驱 的右儿子 .
    • InsertInsert 操作: 直接将 ii 元素 与其 前驱/后继 的信息 进行交换即可 .
    • AskAsk 操作: 直接将 ii 旋转到根, 输出其左子树大小即可 .
    • QueryQuery 操作: 查询第 KK 大即可 .

    color{red}{实现部分}

    • 注意 rotaterotatesizesize 的赋值顺序 .
    • 交换时交换的是位置, 不是值, 只要将相关映射和对应位置上的值交换即可 .
    #include<bits/stdc++.h>
    #define reg register
    
    int read(){
            char c;
            int s = 0, flag = 1;
            while((c=getchar()) && !isdigit(c))
                    if(c == '-'){ flag = -1, c = getchar(); break ; }
            while(isdigit(c)) s = s*10 + c-'0', c = getchar();
            return s * flag;
    }
    
    const int maxn = 80005;
    
    int N;
    int M;
    int Mp[maxn];
    
    char Smp[10];
    
    namespace BBT{
    
            int rot;
            int node_cnt;
    
            struct Node{ int v, fa, son[2], size; } T[maxn];
    
            bool chk(int x){ return T[T[x].fa].son[0] != x; }
    
            void rotate(int x){
                    int y = T[x].fa, z = T[y].fa;
                    int dir = chk(x), sn = T[x].son[dir^1];
                    if(y == rot) rot = x;
                    else T[z].son[chk(y)] = x; T[x].fa = z;
                    T[y].son[dir] = sn, T[sn].fa = y;
                    T[x].son[dir^1] = y, T[y].fa = x; 
                    T[y].size = T[T[y].son[0]].size + T[T[y].son[1]].size + 1;
                    T[x].size = T[T[x].son[0]].size + T[T[x].son[1]].size + 1;
            }
    
            void Splay(int x, int aim=0){
                    while(T[x].fa != aim){
                            int y = T[x].fa, z = T[y].fa;
                            if(z != aim){
                                    if(chk(x) == chk(y)) rotate(y);
                                    else rotate(x);
                            }
                            rotate(x);
                    }
            }
            
            int Kth(int k, int aim){
                    int ls = T[k].son[0];
                    if(T[ls].size + 1 == aim) return k;
                    else if(T[ls].size >= aim) return Kth(ls, aim);
                    return Kth(T[k].son[1], aim - T[ls].size - 1);
            }
    
            void Add_node(int x){
                    Mp[x] = ++ node_cnt, T[node_cnt] = (Node){ x, 0, {0,0}, 1 };
                    if(node_cnt > 1){
                            T[node_cnt-1].son[1] = node_cnt, T[node_cnt].fa = node_cnt - 1;
                            Splay(node_cnt);
                    }
            }
    
            void Top(int k){
                    Splay(k);
    
                    if(!T[k].son[0]) return ;
                    else if(!T[k].son[1]){ T[k].son[1] = T[k].son[0], T[k].son[0] = 0; return ; } 
    
                    int ls = T[k].son[0];
                    int y = Kth(rot, T[ls].size+2);
                    T[y].son[0] = ls, T[ls].fa = y, T[k].son[0] = 0;
                    Splay(y);
            }
    
            void Bottom(int k){
                    Splay(k);
                    if(!T[k].son[1]) return ;
                    else if(!T[k].son[0]){ T[k].son[0] = T[k].son[1], T[k].son[1] = 0; return ; }
                    int ls = T[k].son[0], rs = T[k].son[1];
                    int y = Kth(rot, T[ls].size);
                    T[y].son[1] = rs, T[rs].fa = y, T[k].son[1] = 0;
                    Splay(y);
            }
    
            void Insert(int k, int opt){
                    if(!opt) return ;
                    Splay(k);
                    int rk = T[T[k].son[0]].size + 1, y = Kth(rot, rk + opt);
                    std::swap(Mp[T[k].v], Mp[T[y].v]);
                    std::swap(T[k].v, T[y].v);
    
            }
    
            void Ask(int k){ Splay(k); printf("%d
    ", T[T[k].son[0]].size); }
    
            void Query(int rk){ int y = Kth(rot, rk); printf("%d
    ", T[y].v); }
    
    } 
    
    void Work(){
            scanf("%s", Smp);
            int x = read();
            if(Smp[0] == 'T') BBT::Top(Mp[x]);
            else if(Smp[0] == 'B') BBT::Bottom(Mp[x]);
            else if(Smp[0] == 'I') BBT::Insert(Mp[x], read());
            else if(Smp[0] == 'A') BBT::Ask(Mp[x]);
            else BBT::Query(x);
    }
    
    int main(){
            N = read(), M = read();
            BBT::rot = 1;
            for(reg int i = 1; i <= N; i ++) BBT::Add_node(read());
            while(M --) Work();
            return 0;
    }
    
  • 相关阅读:
    设计模式-中介者模式
    设计模式-中介者模式
    设计模式-职责链模式
    设计模式-职责链模式
    设计模式-命令模式
    设计模式-命令模式
    设计模式-桥接模式
    模乘逆元与孙子定理
    网贷野蛮生长加速 超百亿平台频频涌现
    获乐视千万投资 电桩“傍上大款”
  • 原文地址:https://www.cnblogs.com/zbr162/p/11822672.html
Copyright © 2020-2023  润新知