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