可持久化Treap

函数意义

可持久化Treap本质上市一个二叉平衡树,若不对其规则进行修改,中序遍历后得出的序列是递增的。
void maintain(o): 计算结点o的size
int lowCount(key): 比key所在位置小1
int upperCount(key): key所在的位置,如果有多个相同的key,选位置最大的
int select(int k): 找出第k小的数的值
Node* merge(Node* a, Node* b): 合并,要用rank来合并
void split(Node*a, int k, Node*& l, Node*& r): 拆分,k包含在l中
int rank(int key): key的排名
void insert(int key): 插入key
int pred(int key): 找前驱,比key小的数中最大的那个
int succ(int key):找后继,比key大的数中最小的那个

数组版(洛谷平衡树模板题)

#include <iostream>
using namespace std;
const int maxn = 1e6+5;
#define lc son[o][0]
#define rc son[o][1]
struct Treap {
    int son[maxn][2], val[maxn], r[maxn], sz[maxn];
    bool flag[maxn];
    int root,tot;
    int node(int x) {
        val[tot] = x;
        sz[tot] = 1;
        son[tot][0] = son[tot][1] = 0;
        flag[tot] = false;
        r[tot] = rand();
        return tot++;
    }
    void init() {
        root = 0; tot = 1;
        son[0][0] = son[1][0] = sz[0] = r[0] = 0;
    }
    void maintain(int o) {
        sz[o] = 1;
        sz[o] += (sz[lc]+sz[rc]);
    }
    void split(int o, int k, int &l, int &r) {
        if(o == 0) {
            l = r = 0;
        }
        else if(sz[lc] >= k) {
            r = o;
            split(lc, k, l, lc);
            maintain(o);
        }
        else {
            l = o;
            split(rc, k-sz[lc]-1, rc, r);
            maintain(o);
        }
    }
    int merge(int a,int b) {
        if(a == 0 || b == 0) {
            return a+b;
        }
        if(r[a] < r[b]) { // 必须按rank
            son[a][1] = merge(son[a][1], b);
            maintain(a);
            return a;
        }
        else {
            son[b][0] = merge(a, son[b][0]);
            maintain(b);
            return b;
        }
    }   
    
    int lowCount(int o,int x){
        if(o == 0)
            return 0;
        return val[o] >= x ? lowCount(lc, x) : lowCount(rc, x)+sz[lc]+1;
    }
    int upCount(int o, int x) {
        if(o == 0)
            return 0;
        return val[o] > x ? upCount(lc, x) : upCount(rc, x)+sz[lc]+1;
    }
    int rank(int x) {
        return lowCount(root, x)+1;
    }
    int kth(int k) {
        return select(root, k);
    }
    int select(int o, int k) {
        while(sz[lc]+1 != k) {
            if(sz[lc] >= k) {
                o = lc;
            }
            else {
                k -= (sz[lc]+1);
                o = rc;
            }
        }
        return val[o];
    }
    
    void insert(int x) {
        int pos = lowCount(root, x);
        int a,b;
        split(root, pos, a, b);
        int t = node(x);
        root = merge(merge(a, t), b);
    }
    void del(int val){
        int pos = lowCount(root, val);
        int a,b,x,y;
        split(root, pos, a, b);
        split(b, 1, x, y);
        root = merge(a, y);
    }
    int pred(int x) {
        return kth(lowCount(root, x));
    }
    int succ(int x) {
        return kth(upCount(root, x)+1);
    }
    void show() {
        print(root);
    }
    void print(int o) {
        if(lc != 0)
            print(lc);
        cout << val[o] << endl;
        if(rc != 0)
            print(rc);
    }
};
Treap treap;
typedef long long ll;
inline int readInt() {
    int n = 0, ch = getchar();
    bool flag = false;
    while (!isdigit(ch)) flag |= ch == '-', ch = getchar();
    while (isdigit(ch)) n = n * 10 + ch - '0', ch = getchar();
    return flag ? -n : n;
}
int main() {
    int n;
    treap.init();
    scanf("%d", &n);
    while(n--) {
        int opt,val;
        opt = readInt();
        val = readInt();
        if(opt == 1) {
            treap.insert(val);
        }
        if(opt == 2) {
            treap.del(val);
        }
        if(opt == 3) {
            cout << treap.rank(val) << endl;
        }
        if(opt == 4) {
            cout << treap.kth(val) << endl;
        }
        if(opt == 5) {
//            treap.show();
            cout << treap.pred(val) << endl;
        }
        if(opt == 6) {
            cout << treap.succ(val) << endl;
        }
    }
//    treap.show();
    return 0;
}

指针版(Uva11922)

#include <iostream>
using namespace std;
const int maxn = 1e6+5;
#define lc son[o][0]
#define rc son[o][1]
struct Treap {
    int son[maxn][2], val[maxn], r[maxn], sz[maxn];
    bool flag[maxn];
    int root,tot;
    int node(int x) {
        val[tot] = x;
        sz[tot] = 1;
        son[tot][0] = son[tot][1] = 0;
        flag[tot] = false;
        r[tot] = rand();
        return tot++;
    }
    void init() {
        root = 0; tot = 1;
        son[0][0] = son[1][0] = sz[0] = r[0] = 0;
    }
    void maintain(int o) {
        sz[o] = 1;
        sz[o] += (sz[lc]+sz[rc]);
    }
    void split(int o, int k, int &l, int &r) {
        if(o == 0) {
            l = r = 0;
        }
        else if(sz[lc] >= k) {
            r = o;
            split(lc, k, l, lc);
            maintain(o);
        }
        else {
            l = o;
            split(rc, k-sz[lc]-1, rc, r);
            maintain(o);
        }
    }
    int merge(int a,int b) {
        if(a == 0 || b == 0) {
            return a+b;
        }
        if(r[a] < r[b]) { // 必须按rank
            son[a][1] = merge(son[a][1], b);
            maintain(a);
            return a;
        }
        else {
            son[b][0] = merge(a, son[b][0]);
            maintain(b);
            return b;
        }
    }   
    
    int lowCount(int o,int x){
        if(o == 0)
            return 0;
        return val[o] >= x ? lowCount(lc, x) : lowCount(rc, x)+sz[lc]+1;
    }
    int upCount(int o, int x) {
        if(o == 0)
            return 0;
        return val[o] > x ? upCount(lc, x) : upCount(rc, x)+sz[lc]+1;
    }
    int rank(int x) {
        return lowCount(root, x)+1;
    }
    int kth(int k) {
        return select(root, k);
    }
    int select(int o, int k) {
        while(sz[lc]+1 != k) {
            if(sz[lc] >= k) {
                o = lc;
            }
            else {
                k -= (sz[lc]+1);
                o = rc;
            }
        }
        return val[o];
    }
    
    void insert(int x) {
        int pos = lowCount(root, x);
        int a,b;
        split(root, pos, a, b);
        int t = node(x);
        root = merge(merge(a, t), b);
    }
    void del(int val){
        int pos = lowCount(root, val);
        int a,b,x,y;
        split(root, pos, a, b);
        split(b, 1, x, y);
        root = merge(a, y);
    }
    int pred(int x) {
        return kth(lowCount(root, x));
    }
    int succ(int x) {
        return kth(upCount(root, x)+1);
    }
    void show() {
        print(root);
    }
    void print(int o) {
        if(lc != 0)
            print(lc);
        cout << val[o] << endl;
        if(rc != 0)
            print(rc);
    }
};
Treap treap;
typedef long long ll;
inline int readInt() {
    int n = 0, ch = getchar();
    bool flag = false;
    while (!isdigit(ch)) flag |= ch == '-', ch = getchar();
    while (isdigit(ch)) n = n * 10 + ch - '0', ch = getchar();
    return flag ? -n : n;
}
int main() {
    int n;
    treap.init();
    scanf("%d", &n);
    while(n--) {
        int opt,val;
        opt = readInt();
        val = readInt();
        if(opt == 1) {
            treap.insert(val);
        }
        if(opt == 2) {
            treap.del(val);
        }
        if(opt == 3) {
            cout << treap.rank(val) << endl;
        }
        if(opt == 4) {
            cout << treap.kth(val) << endl;
        }
        if(opt == 5) {
//            treap.show();
            cout << treap.pred(val) << endl;
        }
        if(opt == 6) {
            cout << treap.succ(val) << endl;
        }
    }
//    treap.show();
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值