• Splay模板


    打LCT的时候发现Splay很不熟, 因此这里贴一下模板
    洛谷P3369
    https://www.luogu.org/problem/show?pid=3369#sub

    /*
    提一些要注意的点:
    1. 注意判断边界, 不要访问到空节点
    2. 每一次操作或访问完以后, 记得要splay到root
    3. insert操作只要update当前节点和父亲节点即可, 因为还会上旋到root 
    4.牢记双旋的打法
    5. delete时需要把将要delete的点上旋的根, 因此可与find共用函数 
    6. 在找一个bst中原本不存在的点的前驱或后继时, 可先将该点插入, 然后找前驱或后继, 然后再删除 
    */
    #include<cstdio>
    #include<cctype>
    #include<cstring>
    using namespace std;
    void read(int &x)
    {
        x = 0;
        char c;
        int flag = 1;
        while(! isgraph(c = getchar()))
            if(c == '-')
                flag *= - 1;
        while(isgraph(c))
            x = x * 10 + c - '0', c = getchar();
        x *= flag;
    }
    const int MAXN = (int)1e5;
    int top;
    struct node
    {
        int key, cnt, ch[2], size, fa;
    }T[MAXN + 64];
    int root;
    void create(int x)
    {
        T[top].ch[0] = T[top].ch[1] = - 1;
        T[top].key = x;
        T[top].cnt = 1;
        T[top ++].size = 1;
    }
    void update(int u)
    {
        T[u].size = T[u].cnt;
        if(T[u].ch[0] != - 1)
            T[u].size += T[T[u].ch[0]].size;
        if(T[u].ch[1] != - 1)
            T[u].size += T[T[u].ch[1]].size;
    }
    inline int getson(int p)
    {
        return  (p == T[T[p].fa].ch[1]);
    }
    void rotate(int p)
    {
        int fa = T[p].fa, fafa = T[fa].fa, k = getson(p);
        T[fa].ch[k] = T[p].ch[k ^ 1];
        T[T[p].ch[k ^ 1]].fa = T[p].fa;
        T[p].ch[k ^ 1] = fa;
        T[fa].fa = p;
        T[p].fa = fafa;
        if(fafa != - 1)
            T[fafa].ch[T[fafa].ch[1] == fa] = p;
        update(fa), update(p);
    }
    void splay(int u)
    {
        for(int fa; (fa = T[u].fa) != - 1; rotate(u))
            if(T[fa].fa != - 1)
                rotate((getson(u) == getson(fa)) ? fa : u);
        root = u;
    }
    void insert(int x)
    {
        if(root != - 1)
        {
            int p = root, fa = - 1;
            while(1)
            {
                if(T[p].key == x)
                {
                    T[p].cnt ++;
                    update(p), update(fa);
                    //这里只需要更新p和fa就可以了 
                    splay(p);
                    //因为这里还会更新到p到根节点上的所有祖先 
                    break;
                }
                fa = p;
                p = T[p].ch[x > T[fa].key];
                if(p == - 1)
                {
                    create(x);
                    T[top - 1].fa = fa;
                    T[fa].ch[x > T[fa].key] = top - 1;
                    update(fa);
                    splay(top - 1);
                    break;
                }
            }
        }
        else
            create(x), T[top - 1].fa = root, root = top - 1;
    }
    int find(int x) //写得有点奇怪了, 因为强行把两个操作合并在一起233 
    {
        int p = root, sum = 0;
        while(1)
        {
            if(x < T[p].key)
                p = T[p].ch[0];
            else
            {
                sum += (T[p].ch[0] == - 1) ? 0 : T[T[p].ch[0]].size;
                if(x == T[p].key)
                {
                    splay(p);
                    return sum + 1;
                }
                sum += T[p].cnt;
                p = T[p].ch[1];
            }
        }
    }
    int get_pre()
    {
        int p = T[root].ch[0];
        while(T[p].ch[1] != - 1)
            p = T[p].ch[1];
        return p;
    }
    void del(int x) //下面就是无聊的分类讨论了 
    {
        find(x);
        if(T[root].cnt > 1)
        {
            T[root].cnt --;
            update(root);
            return;
        }
        if(T[root].ch[0] == - 1 && T[root].ch[1] == - 1)
        {
            root = - 1;
            return;
        }
        if(T[root].ch[1] == - 1)
        {
            int tmp = root;
            root = T[root].ch[0];
            T[root].fa = - 1;
            return;
        }
        else
        if(T[root].ch[0] == - 1)
        {
            int tmp = root;
            root = T[root].ch[1];
            T[root].fa = - 1;
            return;
        }
        int pre = get_pre(), tmp = root;
        splay(pre);
        T[T[tmp].ch[1]].fa = root;
        T[root].ch[1] = T[tmp].ch[1];
        update(root);
    }
    void print(int x)
    {
        if(x < 0)
            putchar('-');
        if(x == 0)
            putchar('0');
        int ans[10], top = 0;
        while(x)
            ans[top ++] = x % 10, x /= 10;
        for(; top; top --)
            putchar(ans[top - 1] + '0');
    }
    int get_rank(int x)
    {
        int p = root;
        while(1)
        {
            if(T[p].ch[0] != - 1 && x <= T[T[p].ch[0]].size)
                p = T[p].ch[0];
            else
            {
                int tmp = ((T[p].ch[0] != - 1) ? T[T[p].ch[0]].size : 0) + T[p].cnt;
                if(x <= tmp)
                    return T[p].key;
                x -= tmp;
                p = T[p].ch[1];     
            }
        }
    }
    int get_next()
    {
        int p = T[root].ch[1];
        while(T[p].ch[0] != - 1)
            p = T[p].ch[0];
        return p;
    }
    int main()
    {
        #ifndef ONLINE_JUDGE
        freopen("L3369.in", "r", stdin);
        freopen("L3369.out", "w", stdout);
        #endif
        int n;
        read(n);
        root = - 1;
        top = 0;
        for(int i = 0; i < n; i ++)
        {
            int opt, x;
            read(opt), read(x);
            switch (opt)
            {
                case 1: insert(x); break;
                case 2: del(x); break;
                case 3: print(find(x)); putchar('
    '); break;
                case 4: print(get_rank(x)); putchar('
    '); break;
                case 5: 
                {
                    insert(x);
                    print(T[get_pre()].key);
                    putchar('
    ');
                    del(x);
                    break;
                }
                case 6:
                {
                    insert(x);
                    print(T[get_next()].key);
                    putchar('
    ');
                    del(x);
                    break;
                }
            }
        }
    }
  • 相关阅读:
    《BI项目笔记》用Excel2013连接和浏览OLAP多维数据集
    《BI项目笔记》创建计算成员
    《BI项目笔记》多维数据集中度量值设计时的聚合函数
    《BI项目笔记》创建多维数据集Cube(1)
    《BI项目笔记》创建父子维度
    《BI项目笔记》创建时间维度(2)
    《BI项目笔记》数据源视图设置
    《BI项目笔记》创建时间维度(1)
    CreateThread 和_beginthreadex区别
    面向对象的三个基本特征
  • 原文地址:https://www.cnblogs.com/ZeonfaiHo/p/6402841.html
Copyright © 2020-2023  润新知