SBT(Size Balanced Tree)2016.9.6

参考:陈启峰《Size Balanced Tree》

一、定义

节点大小平衡树( Size Balanced Tree,缩写:SBT)是一种自平衡二叉查找树

它是由中国广东中山纪念中学的陈启峰发明的

陈启峰于 2006 年底完成论文《Size Balanced Tree》,并在 2007 年的全国青少年信息学奥林匹克竞赛冬令营中发表

由于 SBT 的拼写很容易找到中文谐音,它常被中国的信息学竞赛选手和 ACM/ICPC 选手们戏称为“傻B树”、“Super BT”等

相比红黑树、AVL树等自平衡二叉查找树,SBT 更易于实现

据陈启峰在论文中称,SBT 是“目前为止速度最快的高级二叉搜索树”

SBT 能在 O(logn) 的时间内完成所有二叉搜索树( BST )的相关操作,而与普通二叉搜索树相比,SBT 仅仅加入了简洁的核心操作 Maintain

由于 SBT 赖以保持平衡的是 size 域而不是其他“无用”的域,它可以很方便地实现动态顺序统计中的 select 和 rank 操作


二、性质

SBT 是一种通过大小(Size)域来保持平衡的二叉搜索树,它也因此得名

它总是满足:

对于 SBT 的每一个节点 t :

性质(a)

size[rson[t]] ≥ size[lson[lson[t]]], size[rson[lson[t]]]

性质(b)

size[lson[t]] ≥ size[rson[rson[t]]], size[lson[rson[t]]]

即每棵子树的大小不小于其兄弟的子树大小



三、旋转(Rotations)

为了保持 BST 平衡,我们通常使用 Rotations 来改变树的形态

Rotations 分为相对的两种类型:

Right - Rotate

Left - Rotate



Right - Rotate



四、Maintain

当我们插入或删除一个结点后,SBT的大小就发生了改变

这种改变有可能导致性质 (a) 或 (b) 被破坏

这时,我们需要修复这棵树

Maintain(pnode) 用于修复以 pnode 为根的 SBT

调用 Maintain(pnode) 的前提是 pnode 的子树都已经是 SBT 了


由于性质(a)和(b)是对称的,下面仅对性质(a)被破坏的情况进行分析:

1、Case 1:size[lson[lson[T]]] > size[rson[T]]
size[A] > size[R]


(1)Right - Rotate(T)




(2)Maintain(T)


(3)Maintain(L)



2、Case 2:size[rson[lson[T]]] > size[rson[T]]
size[B] > size[R]


(1)Left - Rotate(L)




(2)Right - Rotate(T)




(3)Maintain(L) & Maintain(T)


(4)Maintain(B)


通常我们可以确保性质(a)或(b)已经被满足了

为了提高效率我们可以增加一个布尔参数 falg 来去除无意义的检查


BZOJ 1208 [HNOI2004]宠物收养所

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <vector>
#include <stack>
#include <map>
#include <cmath>
#include <cctype>
#include <bitset>
#include <ctime>

using namespace std;

#define REP(i, n) for (int i = 0; i < (n); ++i)

typedef long long ll;
typedef unsigned long long ull;
typedef unsigned int uint;
typedef pair<int, int> Pair;

const int mod = 1000000;
const int INF = 0x7fffffff;

struct SBT_Node {
    SBT_Node(int value, SBT_Node* Left, SBT_Node* Right) : key(value), lson(Left), rson(Right) {
        size = 1;
    }
    int key, size;
    SBT_Node* lson;
    SBT_Node* rson;
};

class SBT {
public:
    SBT() : root(NULL) {};
    int size();
    void insert(int key);
    void remove(int key);
    bool find(int key);
    int Pred(int key);
    int Succ(int key);
private:
    SBT_Node* root;
    SBT_Node* insert(SBT_Node* &pnode, int key);
    int remove(SBT_Node* &pnode, int key);
    bool find(SBT_Node* pnode, int key);
    int Pred(SBT_Node* pnode, int pre_key, int key);
    int Succ(SBT_Node* pnode, int next_key, int key);
    int size(SBT_Node* pnode);
    SBT_Node* Left_Rotate(SBT_Node* pnode);
    SBT_Node* Right_Rotate(SBT_Node* pnode);
    SBT_Node* Maintain(SBT_Node* pnode, bool flag);
};

int n;

int main()
{
#ifdef __AiR_H
    freopen("in.txt", "r", stdin);
//    freopen("out.txt", "w", stdout);
#endif // __AiR_H
    int a, b;
    SBT sbt;
    int ans = 0;
    int now_kind = 0;
    scanf("%d", &n);
    while (n--) {
        scanf("%d %d", &a, &b);
        if (sbt.size() == 0 || a == now_kind) {
            sbt.insert(b);
            now_kind = a;
        } else if (sbt.find(b)) {
            sbt.remove(b);
        } else {
            int pre = sbt.Pred(b);
            if (pre == 0) {
                pre = INF;
            }
            int next = sbt.Succ(b);
            if (next == 0) {
                next = INF;
            }
            if (abs(pre-b) <= abs(next-b)) {
                sbt.remove(pre);
                ans += abs(pre-b);
                ans %= mod;
            } else {
                sbt.remove(next);
                ans += abs(next-b);
                ans %= mod;
            }
        }
    }
    printf("%d\n", ans);
    return 0;
}

int SBT::Pred(int key)
{
    return Pred(root, 0, key);
}

int SBT::Pred(SBT_Node* pnode, int pre_key, int key)
{
    if (pnode == NULL) {
        return pre_key;
    }
    if (pnode->key < key) {
        return Pred(pnode->rson, pnode->key, key);
    }
    return Pred(pnode->lson, pre_key, key);
}

int SBT::Succ(int key)
{
    return Succ(root, 0, key);
}

int SBT::Succ(SBT_Node* pnode, int next_key, int key)
{
    if (pnode == NULL) {
        return next_key;
    }
    if (pnode->key > key) {
        return Succ(pnode->lson, pnode->key, key);
    }
    return Succ(pnode->rson, next_key, key);
}

bool SBT::find(int key)
{
    return find(root, key);
}

bool SBT::find(SBT_Node* pnode, int key)
{
    while (pnode != NULL) {
        if (key == pnode->key) {
            return true;
        } else if (key < pnode->key) {
            pnode = pnode->lson;
        } else {
            pnode = pnode->rson;
        }
    }
    return false;
}

void SBT::remove(int key)
{
    remove(root, key);
}

int SBT::remove(SBT_Node* &pnode, int key)
{
    if (pnode == NULL) {
        return 0;
    }
    --pnode->size;
    if (key == pnode->key || (pnode->lson == NULL && key < pnode->key) || (pnode->rson == NULL && key > pnode->key)) {
        int key_t = pnode->key;
        if (pnode->lson == NULL) {
            pnode = pnode->rson;
        } else if (pnode->rson == NULL) {
            pnode = pnode->lson;
        } else {
            pnode->key = remove(pnode->lson, pnode->key + 1);
        }
        return key_t;
    } else if (key < pnode->key) {
        return remove(pnode->lson, key);
    } else {
        return remove(pnode->rson, key);
    }
}

void SBT::insert(int key)
{
    insert(root, key);
}

SBT_Node* SBT::insert(SBT_Node* &pnode, int key)
{
    if (pnode == NULL) {
        pnode = new SBT_Node(key, NULL, NULL);
    } else {
        ++pnode->size;
        if (key < pnode->key) {
            pnode->lson = insert(pnode->lson, key);
        } else {
            pnode->rson = insert(pnode->rson, key);
        }
        pnode = Maintain(pnode, key >= pnode->key);
    }
    return pnode;
}

SBT_Node* SBT::Maintain(SBT_Node* pnode, bool flag)
{
    if (!flag) {
        if (pnode->lson != NULL && size(pnode->lson->lson) > size(pnode->rson)) {
            pnode = Right_Rotate(pnode);
        } else if (pnode->lson != NULL && size(pnode->lson->rson) > size(pnode->rson)) {
            pnode->lson = Left_Rotate(pnode->lson);
            pnode = Right_Rotate(pnode);
        } else {
            return pnode;
        }
    } else {
        if (pnode->rson != NULL && size(pnode->rson->rson) > size(pnode->lson)) {
            pnode = Left_Rotate(pnode);
        } else if (pnode->rson != NULL && size(pnode->rson->lson) > size(pnode->lson)) {
            pnode->rson = Right_Rotate(pnode->rson);
            pnode = Left_Rotate(pnode);
        } else {
            return pnode;
        }
    }
    pnode->lson = Maintain(pnode->lson, false);
    pnode->rson = Maintain(pnode->rson, true);
    pnode = Maintain(pnode, false);
    pnode = Maintain(pnode, true);
    return pnode;
}

SBT_Node* SBT::Left_Rotate(SBT_Node* pnode)
{
    SBT_Node* pt = pnode->rson;
    pnode->rson = pt->lson;
    pt->lson = pnode;
    pt->size = size(pnode);
    pnode->size = size(pnode->lson) + size(pnode->rson) + 1;
    return pt;
}

SBT_Node* SBT::Right_Rotate(SBT_Node* pnode)
{
    SBT_Node* pt = pnode->lson;
    pnode->lson = pt->rson;
    pt->rson = pnode;
    pt->size = size(pnode);
    pnode->size = size(pnode->lson) + size(pnode->rson) + 1;
    return pt;
}

int SBT::size()
{
    return size(root);
}

int SBT::size(SBT_Node* pnode)
{
    if (pnode == NULL) {
        return 0;
    }
    return pnode->size;
}



BZOJ 1503 [NOI2004]郁闷的出纳员

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <vector>
#include <stack>
#include <map>
#include <cmath>
#include <cctype>
#include <bitset>
#include <ctime>

using namespace std;

#define REP(i, n) for (int i = 0; i < (n); ++i)

typedef long long ll;
typedef unsigned long long ull;
typedef unsigned int uint;
typedef pair<int, int> Pair;

const int mod = 1000000;
const int INF = 0x7fffffff;

struct SBT_Node {
    SBT_Node(int value, SBT_Node* Left, SBT_Node* Right) : key(value), lson(Left), rson(Right) {
        size = 1;
    }
    int key, size;
    SBT_Node* lson;
    SBT_Node* rson;
};

class SBT {
public:
    SBT() : root(NULL) {};
    int size();
    void insert(int key);
    void remove(int key);
    int find_by_order(int k);
private:
    SBT_Node* root;
    SBT_Node* insert(SBT_Node* &pnode, int key);
    int remove(SBT_Node* &pnode, int key);
    int find_by_order(SBT_Node* pnode, int k);
    int size(SBT_Node* pnode);
    SBT_Node* Left_Rotate(SBT_Node* pnode);
    SBT_Node* Right_Rotate(SBT_Node* pnode);
    SBT_Node* Maintain(SBT_Node* pnode, bool flag);
};

int n, Min, k;
char cmd[1];

int main()
{
#ifdef __AiR_H
    freopen("in.txt", "r", stdin);
//    freopen("out.txt", "w", stdout);
#endif // __AiR_H
    scanf("%d %d", &n, &Min);
    SBT sbt;
    int adjust = 0, leave = 0;
    while (n--) {
        scanf("%s %d", cmd, &k);
        if (cmd[0] == 'I') {
            if (k >= Min) {
                sbt.insert(k - adjust);
            }
        } else if (cmd[0] == 'A') {
            adjust += k;
        } else if (cmd[0] == 'S') {
            adjust -= k;
            int t = 0;
            while (sbt.size() > 0 && (t = sbt.find_by_order(1)) + adjust < Min) {
                sbt.remove(t);
                ++leave;
            }
        } else {
            if (k > sbt.size()) {
                printf("-1\n");
            } else {
                printf("%d\n", sbt.find_by_order(sbt.size() + 1 - k) + adjust);
            }
        }
    }
    printf("%d\n", leave);
    return 0;
}

int SBT::find_by_order(int k)
{
    return find_by_order(root, k);
}

int SBT::find_by_order(SBT_Node* pnode, int k)
{
    int lsize = size(pnode->lson);
    if (k <= lsize) {
        return find_by_order(pnode->lson, k);
    } else if (k > lsize + 1) {
        return find_by_order(pnode->rson, k - lsize - 1);
    } else {
        return pnode->key;
    }
}

void SBT::remove(int key)
{
    remove(root, key);
}

int SBT::remove(SBT_Node* &pnode, int key)
{
    if (pnode == NULL) {
        return 0;
    }
    --pnode->size;
    if (key == pnode->key || (pnode->lson == NULL && key < pnode->key) || (pnode->rson == NULL && key > pnode->key)) {
        int key_t = pnode->key;
        if (pnode->lson == NULL) {
            pnode = pnode->rson;
        } else if (pnode->rson == NULL) {
            pnode = pnode->lson;
        } else {
            pnode->key = remove(pnode->lson, pnode->key + 1);
        }
        return key_t;
    } else if (key < pnode->key) {
        return remove(pnode->lson, key);
    } else {
        return remove(pnode->rson, key);
    }
}

void SBT::insert(int key)
{
    insert(root, key);
}

SBT_Node* SBT::insert(SBT_Node* &pnode, int key)
{
    if (pnode == NULL) {
        pnode = new SBT_Node(key, NULL, NULL);
    } else {
        ++pnode->size;
        if (key < pnode->key) {
            pnode->lson = insert(pnode->lson, key);
        } else {
            pnode->rson = insert(pnode->rson, key);
        }
        pnode = Maintain(pnode, key >= pnode->key);
    }
    return pnode;
}

SBT_Node* SBT::Maintain(SBT_Node* pnode, bool flag)
{
    if (!flag) {
        if (pnode->lson != NULL && size(pnode->lson->lson) > size(pnode->rson)) {
            pnode = Right_Rotate(pnode);
        } else if (pnode->lson != NULL && size(pnode->lson->rson) > size(pnode->rson)) {
            pnode->lson = Left_Rotate(pnode->lson);
            pnode = Right_Rotate(pnode);
        } else {
            return pnode;
        }
    } else {
        if (pnode->rson != NULL && size(pnode->rson->rson) > size(pnode->lson)) {
            pnode = Left_Rotate(pnode);
        } else if (pnode->rson != NULL && size(pnode->rson->lson) > size(pnode->lson)) {
            pnode->rson = Right_Rotate(pnode->rson);
            pnode = Left_Rotate(pnode);
        } else {
            return pnode;
        }
    }
    pnode->lson = Maintain(pnode->lson, false);
    pnode->rson = Maintain(pnode->rson, true);
    pnode = Maintain(pnode, false);
    pnode = Maintain(pnode, true);
    return pnode;
}

SBT_Node* SBT::Left_Rotate(SBT_Node* pnode)
{
    SBT_Node* pt = pnode->rson;
    pnode->rson = pt->lson;
    pt->lson = pnode;
    pt->size = size(pnode);
    pnode->size = size(pnode->lson) + size(pnode->rson) + 1;
    return pt;
}

SBT_Node* SBT::Right_Rotate(SBT_Node* pnode)
{
    SBT_Node* pt = pnode->lson;
    pnode->lson = pt->rson;
    pt->rson = pnode;
    pt->size = size(pnode);
    pnode->size = size(pnode->lson) + size(pnode->rson) + 1;
    return pt;
}

int SBT::size()
{
    return size(root);
}

int SBT::size(SBT_Node* pnode)
{
    if (pnode == NULL) {
        return 0;
    }
    return pnode->size;
}


BZOJ 1588 [HNOI2002]营业额统计

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <vector>
#include <stack>
#include <map>
#include <cmath>
#include <cctype>
#include <bitset>
#include <ctime>

using namespace std;

#define REP(i, n) for (int i = 0; i < (n); ++i)

typedef long long ll;
typedef unsigned long long ull;
typedef unsigned int uint;
typedef pair<int, int> Pair;

const int mod = 1000000;
const int INF = 0x7fffffff;

struct SBT_Node {
    SBT_Node(int value, SBT_Node* Left, SBT_Node* Right) : key(value), lson(Left), rson(Right) {
        size = 1;
    }
    int key, size;
    SBT_Node* lson;
    SBT_Node* rson;
};

class SBT {
public:
    SBT() : root(NULL) {};
    int size();
    void insert(int key);
    bool find(int key);
    int Pred(int key);
    int Succ(int key);
private:
    SBT_Node* root;
    SBT_Node* insert(SBT_Node* &pnode, int key);
    bool find(SBT_Node* pnode, int key);
    int Pred(SBT_Node* pnode, int pre_key, int key);
    int Succ(SBT_Node* pnode, int next_key, int key);
    int size(SBT_Node* pnode);
    SBT_Node* Left_Rotate(SBT_Node* pnode);
    SBT_Node* Right_Rotate(SBT_Node* pnode);
    SBT_Node* Maintain(SBT_Node* pnode, bool flag);
};

int main()
{
#ifdef __AiR_H
    freopen("in.txt", "r", stdin);
#endif // __AiR_H
    int n, num, ans = 0;
    scanf("%d", &n);
    SBT sbt;
    scanf("%d", &num);
    sbt.insert(num);
    ans += num;
    --n;
    while (n--) {
        scanf("%d", &num);
        if (!sbt.find(num)) {
            int pre = sbt.Pred(num);
            int next = sbt.Succ(num);
            if (abs(pre-num) <= abs(next-num)) {
                ans += abs(pre-num);
            } else {
                ans += abs(next-num);
            }
            sbt.insert(num);
        }
    }
    printf("%d\n", ans);
    return 0;
}

int SBT::Pred(int key)
{
    return Pred(root, -INF, key);
}

int SBT::Pred(SBT_Node* pnode, int pre_key, int key)
{
    if (pnode == NULL) {
        if (pre_key == -INF) {
            return INF;
        }
        return pre_key;
    }
    if (pnode->key < key) {
        return Pred(pnode->rson, pnode->key, key);
    }
    return Pred(pnode->lson, pre_key, key);
}

int SBT::Succ(int key)
{
    return Succ(root, -INF, key);
}

int SBT::Succ(SBT_Node* pnode, int next_key, int key)
{
    if (pnode == NULL) {
        if (next_key == -INF) {
            return INF;
        }
        return next_key;
    }
    if (pnode->key > key) {
        return Succ(pnode->lson, pnode->key, key);
    }
    return Succ(pnode->rson, next_key, key);
}

bool SBT::find(int key)
{
    return find(root, key);
}

bool SBT::find(SBT_Node* pnode, int key)
{
    while (pnode != NULL) {
        if (key == pnode->key) {
            return true;
        } else if (key < pnode->key) {
            pnode = pnode->lson;
        } else {
            pnode = pnode->rson;
        }
    }
    return false;
}

void SBT::insert(int key)
{
    insert(root, key);
}

SBT_Node* SBT::insert(SBT_Node* &pnode, int key)
{
    if (pnode == NULL) {
        pnode = new SBT_Node(key, NULL, NULL);
    } else {
        ++pnode->size;
        if (key < pnode->key) {
            pnode->lson = insert(pnode->lson, key);
        } else {
            pnode->rson = insert(pnode->rson, key);
        }
        pnode = Maintain(pnode, key >= pnode->key);
    }
    return pnode;
}

SBT_Node* SBT::Maintain(SBT_Node* pnode, bool flag)
{
    if (!flag) {
        if (pnode->lson != NULL && size(pnode->lson->lson) > size(pnode->rson)) {
            pnode = Right_Rotate(pnode);
        } else if (pnode->lson != NULL && size(pnode->lson->rson) > size(pnode->rson)) {
            pnode->lson = Left_Rotate(pnode->lson);
            pnode = Right_Rotate(pnode);
        } else {
            return pnode;
        }
    } else {
        if (pnode->rson != NULL && size(pnode->rson->rson) > size(pnode->lson)) {
            pnode = Left_Rotate(pnode);
        } else if (pnode->rson != NULL && size(pnode->rson->lson) > size(pnode->lson)) {
            pnode->rson = Right_Rotate(pnode->rson);
            pnode = Left_Rotate(pnode);
        } else {
            return pnode;
        }
    }
    pnode->lson = Maintain(pnode->lson, false);
    pnode->rson = Maintain(pnode->rson, true);
    pnode = Maintain(pnode, false);
    pnode = Maintain(pnode, true);
    return pnode;
}

SBT_Node* SBT::Left_Rotate(SBT_Node* pnode)
{
    SBT_Node* pt = pnode->rson;
    pnode->rson = pt->lson;
    pt->lson = pnode;
    pt->size = size(pnode);
    pnode->size = size(pnode->lson) + size(pnode->rson) + 1;
    return pt;
}

SBT_Node* SBT::Right_Rotate(SBT_Node* pnode)
{
    SBT_Node* pt = pnode->lson;
    pnode->lson = pt->rson;
    pt->rson = pnode;
    pt->size = size(pnode);
    pnode->size = size(pnode->lson) + size(pnode->rson) + 1;
    return pt;
}

int SBT::size()
{
    return size(root);
}

int SBT::size(SBT_Node* pnode)
{
    if (pnode == NULL) {
        return 0;
    }
    return pnode->size;
}

UESTC 1339 郭大侠与线上游戏

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <vector>
#include <stack>
#include <map>
#include <cmath>
#include <cctype>
#include <bitset>
#include <ctime>

using namespace std;

#define REP(i, n) for (int i = 0; i < (n); ++i)

typedef long long ll;
typedef unsigned long long ull;
typedef unsigned int uint;
typedef pair<int, int> Pair;

const int mod = 1000000;
const int INF = 0x7fffffff;

struct SBT_Node {
    SBT_Node(int value, SBT_Node* Left, SBT_Node* Right) : key(value), lson(Left), rson(Right) {
        size = repeat = 1;
    }
    int key, size, repeat;
    SBT_Node* lson;
    SBT_Node* rson;
};

class SBT {
public:
    SBT() : root(NULL) {};
    int size();
    void insert(int key);
    void remove(int key);
    int find_by_order(int k);
private:
    SBT_Node* root;
    SBT_Node* insert(SBT_Node* &pnode, int key);
    void remove(SBT_Node* &pnode, int key);
    int remove_all_extents(SBT_Node* &pnode, int key, int repeat);
    int find_by_order(SBT_Node* pnode, int k);
    SBT_Node* max(SBT_Node* pnode);
    SBT_Node* min(SBT_Node* pnode);
    int size(SBT_Node* pnode);
    SBT_Node* Left_Rotate(SBT_Node* pnode);
    SBT_Node* Right_Rotate(SBT_Node* pnode);
    SBT_Node* Maintain(SBT_Node* pnode, bool flag);
};

int n, cmd, x;
queue<int> Q;

int main()
{
#ifdef __AiR_H
    freopen("in.txt", "r", stdin);
#endif // __AiR_H
    SBT sbt;
    int n;
    scanf("%d", &n);
    while (n--) {
        scanf("%d", &cmd);
        if (cmd == 1) {
            scanf("%d", &x);
            Q.push(x);
            sbt.insert(x);
        } else if (cmd == 2) {
            sbt.remove(Q.front());
            Q.pop();
        } else {
            printf("%d\n", sbt.find_by_order(Q.size() / 2 + 1));
        }
    }
    return 0;
}

SBT_Node* SBT::max(SBT_Node* pnode)
{
    if (pnode == NULL) {
        return NULL;
    }
    while (pnode->rson != NULL) {
        pnode = pnode->rson;
    }
    return pnode;
}

SBT_Node* SBT::min(SBT_Node* pnode)
{
    if (pnode == NULL) {
        return NULL;
    }
    while (pnode->lson != NULL) {
        pnode = pnode->lson;
    }
    return pnode;
}

int SBT::find_by_order(int k)
{
    return find_by_order(root, k);
}

int SBT::find_by_order(SBT_Node* pnode, int k)
{
    int lsize = size(pnode->lson);
    if (k <= lsize) {
        return find_by_order(pnode->lson, k);
    } else if (k > lsize + pnode->repeat) {
        return find_by_order(pnode->rson, k - lsize - pnode->repeat);
    }
    return pnode->key;
}

int SBT::remove_all_extents(SBT_Node* &pnode, int key, int repeat)
{
    if (pnode == NULL) {
        return 0;
    }
    pnode->size -= repeat;
    if (key == pnode->key || (pnode->lson == NULL && key < pnode->key) || (pnode->rson == NULL && key > pnode->key)) {
        int key_t = pnode->key;
        if (pnode->lson == NULL) {
            pnode = pnode->rson;
        } else if (pnode->rson == NULL) {
            pnode = pnode->lson;
        } else {
            pnode->key = remove_all_extents(pnode->lson, pnode->key + 1, repeat);
        }
        return key_t;
    } else if (key < pnode->key) {
        return remove_all_extents(pnode->lson, key, repeat);
    } else {
        return remove_all_extents(pnode->rson, key, repeat);
    }
}

void SBT::remove(int key)
{
    remove(root, key);
}

void SBT::remove(SBT_Node* &pnode, int key)
{
    if (pnode == NULL) {
        return;
    }
    --pnode->size;
    if (key == pnode->key) {
        if (pnode->repeat > 1) {
            --pnode->repeat;
        } else if (pnode->lson == NULL || pnode->rson == NULL) {
            if (pnode->lson != NULL) {
                pnode = pnode->lson;
            } else {
                pnode = pnode->rson;
            }
        } else {
            if (size(pnode->lson) > size(pnode->rson)) {
                SBT_Node* pmax = max(pnode->lson);
                pnode->key = pmax->key;
                pnode->repeat = pmax->repeat;
                int repeat = pmax->repeat;
                remove_all_extents(pnode->lson, pmax->key, repeat);
            } else {
                SBT_Node* pmin = min(pnode->rson);
                pnode->key = pmin->key;
                pnode->repeat = pmin->repeat;
                int repeat = pmin->repeat;
                remove_all_extents(pnode->rson, pmin->key, repeat);
            }
        }
    } else if (key < pnode->key) {
        remove(pnode->lson, key);
    } else {
        remove(pnode->rson, key);
    }
}

void SBT::insert(int key)
{
    insert(root, key);
}

SBT_Node* SBT::insert(SBT_Node* &pnode, int key)
{
    if (pnode == NULL) {
        pnode = new SBT_Node(key, NULL, NULL);
    } else {
        ++pnode->size;
        if (key == pnode->key) {
            ++pnode->repeat;
        } else if (key < pnode->key) {
            pnode->lson = insert(pnode->lson, key);
        } else {
            pnode->rson = insert(pnode->rson, key);
        }
        pnode = Maintain(pnode, key >= pnode->key);
    }
    return pnode;
}

SBT_Node* SBT::Maintain(SBT_Node* pnode, bool flag)
{
    if (!flag) {
        if (pnode->lson != NULL && size(pnode->lson->lson) > size(pnode->rson)) {
            pnode = Right_Rotate(pnode);
        } else if (pnode->lson != NULL && size(pnode->lson->rson) > size(pnode->rson)) {
            pnode->lson = Left_Rotate(pnode->lson);
            pnode = Right_Rotate(pnode);
        } else {
            return pnode;
        }
    } else {
        if (pnode->rson != NULL && size(pnode->rson->rson) > size(pnode->lson)) {
            pnode = Left_Rotate(pnode);
        } else if (pnode->rson != NULL && size(pnode->rson->lson) > size(pnode->lson)) {
            pnode->rson = Right_Rotate(pnode->rson);
            pnode = Left_Rotate(pnode);
        } else {
            return pnode;
        }
    }
    pnode->lson = Maintain(pnode->lson, false);
    pnode->rson = Maintain(pnode->rson, true);
    pnode = Maintain(pnode, false);
    pnode = Maintain(pnode, true);
    return pnode;
}

SBT_Node* SBT::Left_Rotate(SBT_Node* pnode)
{
    SBT_Node* pt = pnode->rson;
    pnode->rson = pt->lson;
    pt->lson = pnode;
    pt->size = size(pnode);
    pnode->size = size(pnode->lson) + size(pnode->rson) + pnode->repeat;
    return pt;
}

SBT_Node* SBT::Right_Rotate(SBT_Node* pnode)
{
    SBT_Node* pt = pnode->lson;
    pnode->lson = pt->rson;
    pt->rson = pnode;
    pt->size = size(pnode);
    pnode->size = size(pnode->lson) + size(pnode->rson) + pnode->repeat;
    return pt;
}

int SBT::size()
{
    return size(root);
}

int SBT::size(SBT_Node* pnode)
{
    if (pnode == NULL) {
        return 0;
    }
    return pnode->size;
}


BZOJ 3224 Tyvj 1728 普通平衡树

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <vector>
#include <stack>
#include <map>
#include <cmath>
#include <cctype>
#include <bitset>
#include <ctime>

using namespace std;

#define REP(i, n) for (int i = 0; i < (n); ++i)

typedef long long ll;
typedef unsigned long long ull;
typedef unsigned int uint;
typedef pair<int, int> Pair;

const int mod = 1000000;
const int INF = 0x7fffffff;

struct SBT_Node {
    SBT_Node(int value, SBT_Node* Left, SBT_Node* Right) : key(value), lson(Left), rson(Right) {
        size = repeat = 1;
    }
    int key, size, repeat;
    SBT_Node* lson;
    SBT_Node* rson;
};

class SBT {
public:
    SBT() : root(NULL) {};
    int size();
    void insert(int key);
    void remove(int key);
    int find_by_order(int k);
    int order_of_key(int key);
    int Pred(int key);
    int Succ(int key);
private:
    SBT_Node* root;
    SBT_Node* insert(SBT_Node* &pnode, int key);
    void remove(SBT_Node* &pnode, int key);
    int remove_all_extents(SBT_Node* &pnode, int key, int repeat);
    int find_by_order(SBT_Node* pnode, int k);
    int order_of_key(SBT_Node* pnode, int key);
    SBT_Node* max(SBT_Node* pnode);
    SBT_Node* min(SBT_Node* pnode);
    int Pred(SBT_Node* pnode, int pre_key, int key);
    int Succ(SBT_Node* pnode, int next_key, int key);
    int size(SBT_Node* pnode);
    SBT_Node* Left_Rotate(SBT_Node* pnode);
    SBT_Node* Right_Rotate(SBT_Node* pnode);
    SBT_Node* Maintain(SBT_Node* pnode, bool flag);
};

int main()
{
#ifdef __AiR_H
    freopen("in.txt", "r", stdin);
    freopen("6out.txt", "w", stdout);
#endif // __AiR_H
    int n, cmd, x;
    SBT sbt;
    scanf("%d", &n);
    while (n--) {
        scanf("%d %d", &cmd, &x);
        if (cmd == 1) {
            sbt.insert(x);
        } else if (cmd == 2) {
            sbt.remove(x);
        } else if (cmd == 3) {
            printf("%d\n", sbt.order_of_key(x));
        } else if (cmd == 4) {
            printf("%d\n", sbt.find_by_order(x));
        } else if (cmd == 5) {
            printf("%d\n", sbt.Pred(x));
        } else {
            printf("%d\n", sbt.Succ(x));
        }
    }
    return 0;
}

SBT_Node* SBT::max(SBT_Node* pnode)
{
    if (pnode == NULL) {
        return NULL;
    }
    while (pnode->rson != NULL) {
        pnode = pnode->rson;
    }
    return pnode;
}

SBT_Node* SBT::min(SBT_Node* pnode)
{
    if (pnode == NULL) {
        return NULL;
    }
    while (pnode->lson != NULL) {
        pnode = pnode->lson;
    }
    return pnode;
}

int SBT::order_of_key(int key)
{
    return order_of_key(root, key);
}

int SBT::order_of_key(SBT_Node* pnode, int key)
{
    if (key < pnode->key) {
        return order_of_key(pnode->lson, key);
    } else if (key > pnode->key) {
        return order_of_key(pnode->rson, key) + size(pnode->lson) + pnode->repeat;
    }
    return size(pnode->lson) + 1;
}

int SBT::Pred(int key)
{
    return Pred(root, -INF, key);
}

int SBT::Pred(SBT_Node* pnode, int pre_key, int key)
{
    if (pnode == NULL) {
        if (pre_key == -INF) {
            return INF;
        }
        return pre_key;
    }
    if (pnode->key < key) {
        return Pred(pnode->rson, pnode->key, key);
    }
    return Pred(pnode->lson, pre_key, key);
}

int SBT::Succ(int key)
{
    return Succ(root, -INF, key);
}

int SBT::Succ(SBT_Node* pnode, int next_key, int key)
{
    if (pnode == NULL) {
        if (next_key == -INF) {
            return INF;
        }
        return next_key;
    }
    if (pnode->key > key) {
        return Succ(pnode->lson, pnode->key, key);
    }
    return Succ(pnode->rson, next_key, key);
}

int SBT::find_by_order(int k)
{
    return find_by_order(root, k);
}

int SBT::find_by_order(SBT_Node* pnode, int k)
{
    int lsize = size(pnode->lson);
    if (k <= lsize) {
        return find_by_order(pnode->lson, k);
    } else if (k > lsize + pnode->repeat) {
        return find_by_order(pnode->rson, k - lsize - pnode->repeat);
    }
    return pnode->key;
}

int SBT::remove_all_extents(SBT_Node* &pnode, int key, int repeat)
{
    if (pnode == NULL) {
        return 0;
    }
    pnode->size -= repeat;
    if (key == pnode->key || (pnode->lson == NULL && key < pnode->key) || (pnode->rson == NULL && key > pnode->key)) {
        int key_t = pnode->key;
        if (pnode->lson == NULL) {
            pnode = pnode->rson;
        } else if (pnode->rson == NULL) {
            pnode = pnode->lson;
        } else {
            pnode->key = remove_all_extents(pnode->lson, pnode->key + 1, repeat);
        }
        return key_t;
    } else if (key < pnode->key) {
        return remove_all_extents(pnode->lson, key, repeat);
    } else {
        return remove_all_extents(pnode->rson, key, repeat);
    }
}

void SBT::remove(int key)
{
    remove(root, key);
}

void SBT::remove(SBT_Node* &pnode, int key)
{
    if (pnode == NULL) {
        return;
    }
    --pnode->size;
    if (key == pnode->key) {
        if (pnode->repeat > 1) {
            --pnode->repeat;
        } else if (pnode->lson == NULL || pnode->rson == NULL) {
            if (pnode->lson != NULL) {
                pnode = pnode->lson;
            } else {
                pnode = pnode->rson;
            }
        } else {
            if (size(pnode->lson) > size(pnode->rson)) {
                SBT_Node* pmax = max(pnode->lson);
                pnode->key = pmax->key;
                pnode->repeat = pmax->repeat;
                int repeat = pmax->repeat;
                remove_all_extents(pnode->lson, pmax->key, repeat);
            } else {
                SBT_Node* pmin = min(pnode->rson);
                pnode->key = pmin->key;
                pnode->repeat = pmin->repeat;
                int repeat = pmin->repeat;
                remove_all_extents(pnode->rson, pmin->key, repeat);
            }
        }
    } else if (key < pnode->key) {
        remove(pnode->lson, key);
    } else {
        remove(pnode->rson, key);
    }
}

void SBT::insert(int key)
{
    insert(root, key);
}

SBT_Node* SBT::insert(SBT_Node* &pnode, int key)
{
    if (pnode == NULL) {
        pnode = new SBT_Node(key, NULL, NULL);
    } else {
        ++pnode->size;
        if (key == pnode->key) {
            ++pnode->repeat;
        } else if (key < pnode->key) {
            pnode->lson = insert(pnode->lson, key);
        } else {
            pnode->rson = insert(pnode->rson, key);
        }
        pnode = Maintain(pnode, key >= pnode->key);
    }
    return pnode;
}

SBT_Node* SBT::Maintain(SBT_Node* pnode, bool flag)
{
    if (!flag) {
        if (pnode->lson != NULL && size(pnode->lson->lson) > size(pnode->rson)) {
            pnode = Right_Rotate(pnode);
        } else if (pnode->lson != NULL && size(pnode->lson->rson) > size(pnode->rson)) {
            pnode->lson = Left_Rotate(pnode->lson);
            pnode = Right_Rotate(pnode);
        } else {
            return pnode;
        }
    } else {
        if (pnode->rson != NULL && size(pnode->rson->rson) > size(pnode->lson)) {
            pnode = Left_Rotate(pnode);
        } else if (pnode->rson != NULL && size(pnode->rson->lson) > size(pnode->lson)) {
            pnode->rson = Right_Rotate(pnode->rson);
            pnode = Left_Rotate(pnode);
        } else {
            return pnode;
        }
    }
    pnode->lson = Maintain(pnode->lson, false);
    pnode->rson = Maintain(pnode->rson, true);
    pnode = Maintain(pnode, false);
    pnode = Maintain(pnode, true);
    return pnode;
}

SBT_Node* SBT::Left_Rotate(SBT_Node* pnode)
{
    SBT_Node* pt = pnode->rson;
    pnode->rson = pt->lson;
    pt->lson = pnode;
    pt->size = size(pnode);
    pnode->size = size(pnode->lson) + size(pnode->rson) + pnode->repeat;
    return pt;
}

SBT_Node* SBT::Right_Rotate(SBT_Node* pnode)
{
    SBT_Node* pt = pnode->lson;
    pnode->lson = pt->rson;
    pt->rson = pnode;
    pt->size = size(pnode);
    pnode->size = size(pnode->lson) + size(pnode->rson) + pnode->repeat;
    return pt;
}

int SBT::size()
{
    return size(root);
}

int SBT::size(SBT_Node* pnode)
{
    if (pnode == NULL) {
        return 0;
    }
    return pnode->size;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值