[BZOJ 3224] 普通平衡树 非旋Treap

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[BZOJ 3224] 普通平衡树 非旋Treap相关的知识,希望对你有一定的参考价值。

题意

  维护一个多重集合 $S$ , 支持:

    ① 插入一个数 $w$ .

    ② 删除一个数 $w$ .

    ③ 查询 $w$ 在集合中的排名.

    ④ 查询集合中排名第 $r$ 的数.

    ⑤ 求集合中 $w$ 的前驱.

    ⑥ 求集合中 $w$ 的后继.

  $N \le 100000$ .

 

小结

  要总结一些常见的写法和想法, 减小实现时的复杂度.

 

实现

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cctype>

#define F(i, a, b) for (register int i = (a); i <= (b); i++)

const int N = 100005;

int n;
int rt, tot, c[N][2], siz[N], fix[N], key[N];
struct D { int c[2]; };

inline int rd(void) {
    int f = 1; char c = getchar(); for (; !isdigit(c); c = getchar()) if (c == -) f = -1;
    int x = 0; for (; isdigit(c); c = getchar()) x = x*10+c-0; return x*f;
}

inline void Pushup(int x) { siz[x] = siz[c[x][0]] + siz[c[x][1]] + 1; }
inline int Merge(int x, int y) {
    if (!x || !y) return x+y;
    if (fix[x] < fix[y]) {
        c[x][1] = Merge(c[x][1], y);
        Pushup(x);
        return x;
    }
    else {
        c[y][0] = Merge(x, c[y][0]);
        Pushup(y);
        return y;
    }
}
inline D Split(int x, int k) {
    if (!x) return D();
    if (key[x] > k) {
        D t = Split(c[x][0], k);
        c[x][0] = t.c[1], Pushup(x);
        t.c[1] = x;
        return t;
    }
    else {
        D t = Split(c[x][1], k);
        c[x][1] = t.c[0], Pushup(x);
        t.c[0] = x;
        return t;
    }
}
inline D Split_r(int x, int k) {
    if (!x) return D();
    if (siz[c[x][0]] + 1 > k) {
        D t = Split_r(c[x][0], k);
        c[x][0] = t.c[1], Pushup(x);
        t.c[1] = x;
        return t;
    }
    else {
        D t = Split_r(c[x][1], k-siz[c[x][0]]-1);
        c[x][1] = t.c[0], Pushup(x);
        t.c[0] = x;
        return t;
    }
}

inline int Newnode(int w) { return siz[++tot] = 1, fix[tot] = rand(), key[tot] = w, tot; }
inline void Insert(int w) {
    int x = Newnode(w);
    D t = Split(rt, w);
    rt = Merge(Merge(t.c[0], x), t.c[1]);
}
inline void Delete(int w) {
    //It‘s guaranteed that w exists!
    D t = Split(rt, w-1);
    D tx = Split_r(t.c[1], 1);
    rt = Merge(t.c[0], tx.c[1]);
}
inline int Get(int w) {
    D t = Split(rt, w-1);
    int res = siz[t.c[0]] + 1;
    rt = Merge(t.c[0], t.c[1]);
    return res;
}
inline int Rank(int k) {
    D t = Split_r(rt, k-1);
    D tx = Split_r(t.c[1], 1);
    int res = key[tx.c[0]];
    rt = Merge(t.c[0], Merge(tx.c[0], tx.c[1]));
    return res;
}
inline int Pre(int w) {
    D t = Split(rt, w-1);
    D tx = Split_r(t.c[0], siz[t.c[0]]-1);
    int res = key[tx.c[1]];
    rt = Merge(Merge(tx.c[0], tx.c[1]), t.c[1]);
    return res;
}
inline int Nxt(int w) {
    D t = Split(rt, w);
    D tx = Split_r(t.c[1], 1);
    int res = key[tx.c[0]];
    rt = Merge(t.c[0], Merge(tx.c[0], tx.c[1]));
    return res;
}

int main(void) {
    #ifndef ONLINE_JUDGE
        freopen("bzoj3224.in", "r", stdin);
        freopen("bzoj3224.out", "w", stdout);
    #endif
    
    n = rd();
    F(i, 1, n) {
        int k = rd(), x = rd();
        if (k == 1) Insert(x);
        else if (k == 2) Delete(x);
        else if (k == 3) printf("%d\n", Get(x));
        else if (k == 4) printf("%d\n", Rank(x));
        else if (k == 5) printf("%d\n", Pre(x));
        else printf("%d\n", Nxt(x));
    }
    
    return 0;
}

 

以上是关于[BZOJ 3224] 普通平衡树 非旋Treap的主要内容,如果未能解决你的问题,请参考以下文章

[BZOJ3224]普通平衡树(旋转treap)

bzoj3224: Tyvj 1728 普通平衡树 treap

bzoj3224普通平衡树——treap

BZOJ 3224 普通平衡树(treap模板题)

Treap模板详细注释BZOJ3224-普通平衡树

BZOJ3224: Tyvj 1728 普通平衡树[treap]