zoukankan      html  css  js  c++  java
  • 【code】Splay 模板

    #include <bits/stdc++.h>
    using namespace std;
    const int INF = 0x3f3f3f3f;
    
    // Splay
    class Splay{
        #define root T[0].son[1]  //T[0]为超级根,树根为超级根的右孩子
        private:
            struct Tree{  //一个节点只存储一个数值,一个数值只由一个点存储
                int fa, son[2]/*0 左,1 右*/, v/*当前节点数值*/, sum/*以当前节点为根的树中所有数值的数量*/, recy/*当前点的数值的数量*/;
            }T[100005];
            int ctp/*数值数量*/, ctn/*节点编号*/;
            void update(int k){  //更新sum
                T[k].sum = T[T[k].son[1]].sum+T[T[k].son[0]].sum+T[k].recy;
            }
            int identify(int k){  //识别自己是左(右)孩子
                return T[T[k].fa].son[0]==k?0:1;
            }
            void connect(int s, int f, int lr){  //建立两点间父子关系
                T[s].fa = f, T[f].son[lr] = s;
            }
            void rotate(int k){  //左(右)旋操作
                int p = T[k].fa, q = T[p].fa;
                int lrk = identify(k), lrp = identify(p);
                int b = T[k].son[lrk^1];
                connect(b, p, lrk), connect(p, k, lrk^1), connect(k, q, lrp);
                update(p), update(k);
            }
            void splay(int k, int to){  //核心 将点 k 旋转到点 to
                to = T[to].fa; int up;
                while(T[k].fa != to){
                    up = T[k].fa;
                    if(T[up].fa == to) rotate(k);
                    else{
                        identify(k)==identify(up)?rotate(up):rotate(k);
                        rotate(k);
                    }
                }
            }
            int creat(int v, int fa){  //新建点
                T[++ctn].fa = fa, T[ctn].v = v;
                T[ctn].sum = T[ctn].recy = 1;
                return ctn;
            }
            void destory(int k){  //摧毁点
                T[k].fa = T[k].sum = T[k].son[1] = T[k].son[0] = T[k].recy = 0;
            }
            int find(int v){  //查找点
                int k = root, next;
                while(T[k].v != v){
                    next = v<T[k].v?0:1;
                    if(!T[k].son[next]) return 0;
                    k = T[k].son[next];
                }
                splay(k, root);
                return k;
            }
            int build(int v){  //没有splay的push(见下方push)
                if(!ctp++){
                    root = creat(v, 0);
                    return 0;
                }
                int k = root, next;
                while(T[k].v != v){
                    T[k].sum++;
                    next = v<T[k].v?0:1;
                    if(!T[k].son[next]) return T[k].son[next] = creat(v, k);
                    k = T[k].son[next];
                }
                T[k].sum++;
                T[k].recy++;
                return k;
            }
        public:
            void push(int v){  //插入一个数值
                splay(build(v), root);
            }
            void pop(int v){  //删除一个数值
                int k = find(v);
                if(!k) return;
                ctp--;
                if(T[k].recy > 1){
                    T[k].recy--;
                    T[k].sum--;
                    return;
                }
                if(!T[k].son[0]) connect(T[k].son[1], 0, 1);
                else if(!T[k].son[1]) connect(T[k].son[0], 0, 1);
                else{
                    int ls = T[k].son[0];
                    while(T[ls].son[1]) ls = T[ls].son[1];
                    splay(ls, T[k].son[0]);
                    int rs = T[k].son[1];
                    connect(rs, ls, 1), connect(ls, 0, 1);
                    update(ls);
                }
                destory(k);
            }
            int rank(int v){  //查询数值 v 的排名
                int k = root, ans = 0;
                if(!root) return 0;
                while(T[k].v != v){
                    if(v < T[k].v) k = T[k].son[0];
                    else{
                        ans += T[T[k].son[0]].sum+T[k].recy;
                        k = T[k].son[1];
                    }
                    if(!k) return 0;
                }
                ans += T[T[k].son[0]].sum+1;
                splay(k, root);
                return ans;
            }
            int atrank(int x){  //查询排名为 x 的数值
                if(x > ctp) return -INF;
                int k = root, p;
                while(1){
                    p = T[T[k].son[0]].sum+T[k].recy;
                    if(x>T[T[k].son[0]].sum && x<=p) break;
                    if(x < p) k = T[k].son[0];
                    else{
                        x -= p;
                        k = T[k].son[1];
                    } 
                }
                splay(k, root);
                return T[k].v;
            }
            int upper(int v){  //查询数值 v 的后继
                int k = root, ans = INF;
                while(k){
                    if(T[k].v>v && T[k].v<ans) ans = T[k].v;
                    if(v < T[k].v) k = T[k].son[0];
                    else k = T[k].son[1];
                }
                return ans;
            }
            int lower(int v){  //查询数值 v 的前驱
                int k = root, ans = -INF;
                while(k){
                    if(T[k].v<v && T[k].v>ans) ans = T[k].v;
                    if(v > T[k].v) k = T[k].son[1];
                    else k = T[k].son[0];
                }
                return ans;
            }
        #undef root
    }W;
    
    // main
    int main(){
        int n, a, b;
        scanf("%d", &n);
        while(n--){
            scanf("%d%d", &a, &b);
            if(a == 1) W.push(b);
            else if(a == 2) W.pop(b);
            else if(a == 3) printf("%d
    ", W.rank(b));
            else if(a == 4) printf("%d
    ", W.atrank(b));
            else if(a == 5) printf("%d
    ", W.lower(b));
            else printf("%d
    ", W.upper(b));
        }
        return 0;
    }
    
  • 相关阅读:
    软工实践第三次作业(结对第一次作业)
    软工实践第四次作业(团队展示)
    软工实践第二次作业(词频统计)
    软工实践第七次作业(软件产品案例分析 )
    安装cordova和ionic遇到cordova v和ionic v出错的问题,出现SyntaxError
    软工实践第八次作业(软件工程实践总结)
    软工实践第六次作业(团队项目作业汇总)
    软工实践第五次作业(结对第二次作业)
    chain of responsibilit职责链模式
    术语
  • 原文地址:https://www.cnblogs.com/bosswnx/p/10570787.html
Copyright © 2011-2022 走看看