zoukankan      html  css  js  c++  java
  • Splay P3369 【模板】普通平衡树(Treap/SBT)

    题目描述

    您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:

    1. 插入x数

    2. 删除x数(若有多个相同的数,因只删除一个)

    3. 查询x数的排名(排名定义为比当前数小的数的个数+1。若有多个相同的数,因输出最小的排名)

    4. 查询排名为x的数

    5. 求x的前驱(前驱定义为小于x,且最大的数)

    6. 求x的后继(后继定义为大于x,且最小的数)

    输入输出格式

    输入格式:

    第一行为n,表示操作的个数,下面n行每行有两个数opt和x,opt表示操作的序号( 1 leq opt leq 61opt6 )

    输出格式:

    对于操作3,4,5,6每行输出一个数,表示对应答案

    输入输出样例

    输入样例#1: 复制
    10
    1 106465
    4 1
    1 317721
    1 460929
    1 644985
    1 84185
    1 89851
    6 81968
    1 492737
    5 493598
    输出样例#1: 复制
    106465
    84185
    492737

    说明

    时空限制:1000ms,128M

    1.n的数据范围: n leq 100000n100000

    2.每个数的数据范围: [-{10}^7, {10}^7][107,107]

    来源:Tyvj1728 原名:普通平衡树

    在此鸣谢

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    
    const int N = 1e5+5;
    const int INF = 599518803;
    
    int n, opt, x;
    struct NODE
    {
        NODE *fa;
        NODE *son[2];
        int siz;
        int num, cnt;
    }node[N];
    
    typedef NODE* Tree;
    Tree Root, now_node, null;
    
    inline void init()
    {
        Root = now_node = null = node;
        null->son[0] = null->son[1] = null;
    }
    
    inline int read()
    {
        char c = getchar(); int num = 0, f = 1;
        for(; !isdigit(c); c = getchar())
            f = c == '-' ? -1 : f;
        for(; isdigit(c); c = getchar())
            num = num * 10 + c - '0';
        return num * f;
    }
    
    
    inline Tree new_node(int num, Tree fa)
    {
        ++ now_node;
        now_node->siz = 1;
        now_node->num = num;
        now_node->fa = fa;
        now_node->son[0] = now_node->son[1] = null;
        return now_node;
    }
    
    inline bool getgx(Tree root)
    {
        return root->fa->son[1] == root;
    }
    
    inline void connect(Tree root, Tree fa, bool flag)
    {
        if(fa != null)
            fa->son[flag] = root;
        else
            Root = root;
        root->fa = fa;
    }
    
    inline void update(Tree root)
    {
        root->siz = root->son[0]->siz + root->son[1]->siz + root->cnt;
    }
    
    inline void rotate(Tree root)
    {
        Tree fa = root->fa;
        bool a = getgx(root), b = !a;
        connect(root->son[b], fa, a);
        connect(root, fa -> fa, getgx(fa));
        connect(fa, root, b);
        update(fa);
        update(root);
        if(root->fa == null)
            Root = root;
    }
    
    inline void splay(Tree root, Tree goal)
    {
        for(; root->fa != goal; rotate(root))
            if(root->fa->fa != goal)
                rotate(getgx(root) == getgx(root->fa) ? root->fa : root);
    }
    
    void insert(int num)
    {
        if(Root == null)
        {
            Root = new_node(num, null);
            Root->cnt = 1;
        }
        else
        {
            Tree root = Root;
            for(; root->num != num; root = root->son[num > root->num])
            {
                ++ (root->siz);
                if(root->son[num > root->num] == null)
                    root->son[num > root->num] = new_node(num, root);
            }
            ++ (root->cnt);
            splay(root, null);
        }
    }
    
    void erase(int num)
    {
        if(Root == null)
            return;
        else
        {
            Tree root = Root;
            for(;root != null && root->num != num; root = root->son[num > root->num]);
            if(root == null)
                return;
            splay(root, null);
            -- (root->cnt);
            if(!root->cnt)
            {
                if(root->son[0] != null)
                {
                    Tree tmp = root->son[0];
                    for(;tmp->son[1] != null; tmp = tmp->son[1]);
                    splay(tmp, null);
                    Root->son[1] = root->son[1];
                    if(Root->son[1] != null)
                        Root->son[1]->fa = Root;
                }
                else
                {
                    Root = root->son[1];
                    Root->fa = null;
                }
            }
        }
    }
    
    inline int query_rank(int num)
    {
        int rank = 0;
        for(Tree root = Root; root != null; root = root->son[num > root->num])
        {
            if(num == root->num)
                return rank + root->son[0]->siz + 1;
            if(num > root->num)
                rank += root->son[0]->siz + root->cnt;
        }
        return rank;
    }
    
    inline int query_num(int rank)
    {
        for(Tree root = Root; root != null; )
        {
            if(rank <= root->son[0]->siz)
                root = root->son[0];
            else if(rank > root->son[0]->siz + root->cnt)
                rank -= root->son[0]->siz + root->cnt, root = root->son[1];
            else
                return root->num;
        }
    }
    
    inline int query_pre(int x)
    {
        int pre = -INF;
        for(Tree root = Root; root != null; root = root->son[x > root->num])
        {
            if(x > root->num)
                pre = max(pre, root->num);
        }
        return pre;
    }
    
    inline int query_nxt(int x)
    {
        int nxt = INF;
        for(Tree root = Root; root != null; root = root->son[x >= root->num])
        {
            if(root->num > x)
                nxt = min(nxt, root->num);
        }
        return nxt;
    }
    
    int main()
    {
        init();
        n = read();
        for(int i = 1; i <= n; ++ i)
        {
            opt = read(), x = read();
            switch(opt)
            {
                case 1:
                    insert(x); break;
                case 2:
                    erase(x); break;
                case 3:
                    printf("%d
    ", query_rank(x)); break;
                case 4:
                    printf("%d
    ", query_num(x)); break;
                case 5:
                    printf("%d
    ", query_pre(x)); break;
                default:
                    printf("%d
    ", query_nxt(x));
            }
        }
        return 0;
    }
  • 相关阅读:
    Firemonkey 控件设定字型属性及颜色
    ListView 使用 LiveBindings 显示超过 200 条记录
    Firemonkey ListView 获取项目右方「>」(Accessory) 事件
    XE7 Update 1 选 iOS 8.1 SDK 发布 iPhone 3GS 实机测试
    Firemonkey Bitmap 设定像素颜色 Pixel
    Firemonkey 移动平台 Form 显示使用 ShowModal 范例
    XE7 提交 App(iOS 8)提示「does not contain the correct beta entitlement」问题修复
    XE7 Android 中使用 MessageDlg 范例
    导出 XE6 预设 Android Style (*.style) 档案
    修正 Memo 設定為 ReadOnly 後, 無法有複製的功能
  • 原文地址:https://www.cnblogs.com/lovewhy/p/8503134.html
Copyright © 2011-2022 走看看