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

    题意简述

    已知一个数列,你需要进行下面六种操作:
    1.插入 x 数
    2.删除 x 数(若有多个相同的数,因只删除一个)
    3.查询 x 数的排名(排名定义为比当前数小的数的个数 +1+1 。若有多个相同的数,因输出最小的排名)
    4.查询排名为 x 的数
    5.求 x 的前驱(前驱定义为小于 x ,且最大的数)
    6.求 x 的后继(后继定义为大于 x ,且最小的数)

    代码

    #include <cstdio>
    #include <algorithm>
    const int INF = 0x3f3f3f3f;
    int n, opt, x, s1, s2;
    struct Node
    {
        int v, s, n;
        Node *c[2];
        Node(int x = 0) {v = x; s = n = 1; c[0] = c[1] = 0; }
        int get(const bool& b) {return c[b] ? c[b] -> s : 0; }
        void update() {s = get(0) + get(1) + n; }
        int cmp(const int& x, const bool& b)
        {
            if (!b) return x == v ? -1 : x > v;
            if (get(0) + 1 <= x && x <= get(0) + n) return -1;
            return x > get(0);
        }
    }*r;
    inline void rotate(Node* &o, const bool& b)
    {
        Node *t = o -> c[!b];
        o -> c[!b] = t -> c[b];
        t -> c[b] = o;
        o -> update(); t -> update();
        o = t;
    }
    void splay(Node* &o, int x, const bool& b)
    {
        int d1 = o -> cmp(x, b);
        if (d1 == -1) return;
        Node* &t = o -> c[d1];
        if (b && d1) x -= o -> get(0) + o -> n;
        int d2 = t -> cmp(x, b);
        if (d2 != -1)
        {
            if (b && d2) x -= t -> get(0) + t -> n;
            splay(t -> c[d2], x, b);
            if (d1 == d2) rotate(o, !d1);
            else rotate(t, !d2);
        }
        rotate(o, !d1);
    }
    void ins(Node* &o, const int& x)
    {
        if (!o) {o = new Node(x); return; }
        Node* t = o;
        int d = t -> cmp(x, 0);
        while (d != -1 && t -> c[d]) t = t -> c[d], d = t -> cmp(x, 0);
        if (d == -1) {++t -> n; t -> update(); return; }
        t -> c[d] = new Node(x);
    }
    inline void del(Node* &o, const int& x)
    {
        splay(o, x, 0);
        if (o -> n > 1) {--o -> n; o -> update(); return; }
        Node* t = o;
        if (!o -> c[0]) {o = o -> c[1]; delete t; return; }
        splay(o -> c[0], o -> get(0), 1);
        o -> c[0] -> c[1] = o -> c[1];
        o = o -> c[0]; o -> update();
        delete t;
    }
    inline int rank(Node* &o, const int& x) {splay(o, x, 0); return o -> get(0) + 1; }
    inline int num(Node* &o, const int& x) {splay(o, x, 1); return o -> v; }
    void pre(Node* &o, const int& x)
    {
        if (!o) return;
        int d = o -> cmp(x, 0);
        if (d == 1) s1 = std::max(s1, o -> v);
        pre(o -> c[d == -1 ? 0 : d], x);
    }
    void suc(Node* &o, const int& x)
    {
        if (!o) return;
        int d = o -> cmp(x, 0);
        if (d == 0) s2 = std::min(s2, o -> v);
        suc(o -> c[d == -1 ? 1 : d], x);
    }
    int main()
    {
        scanf("%d", &n);
        for (register int i = 1; i <= n; ++i)
        {
            scanf("%d%d", &opt, &x);
            if (opt == 1) ins(r, x), splay(r, x, 0);
            else if (opt == 2) del(r, x);
            else if (opt == 3) printf("%d
    ", rank(r, x));
            else if (opt == 4) printf("%d
    ", num(r, x));
            else if (opt == 5) {s1 = -INF; pre(r, x); printf("%d
    ", s1); }
            else {s2 = INF; suc(r, x); printf("%d
    ", s2); }
        }
    }
    
  • 相关阅读:
    【分享】HTML5附件拖拽上传drop & google.gears
    【分享】return false,对阻止事件默认动作的一些测试
    【记录】随笔分类汇总
    【分享】微博 @ 符号的用户名提示效果。(想@到谁?)
    【记录】File, FileReader 和 Ajax 文件上传
    【动态】简单的JS动态加载单体
    【分享】简单页面提示插件第二版表单验证很简单
    【记录】GIT 常用命令
    【分享】jQuery animate自定义动画的简单实现
    【分享】 封装js操作textarea 方法集合(兼容很好)。
  • 原文地址:https://www.cnblogs.com/xuyixuan/p/9445100.html
Copyright © 2011-2022 走看看