参考:陈启峰《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;
}