SBT(Size Balanced Tree)是陈启峰提出的一种平衡二叉树,下面是
他的论文,中文版的论文
在这里。
SBT树模板
const int maxn = 10000000+10;
struct SBT {
int l, r, key, s;
void init(int k) {
l = r = 0, s = 1, key = k;
}
}T[maxn];
int next, root, n, m;
void init() {//初始化SBT树的root和next
next = root = 0;
}
void Right_Rotate(int &t) {//右旋转
int k = T[t].l;
T[t].l = T[k].r;
T[k].r = t;
T[k].s = T[t].s;
T[t].s = T[T[t].l].s+T[T[t].r].s+1;
t = k;
}
void Left_Rotate(int &t) {//左旋转
int k = T[t].r;
T[t].r = T[k].l;
T[k].l = t;
T[k].s = T[t].s;
T[t].s = T[T[t].l].s+T[T[t].r].s+1;
t = k;
}
void Maintain(int &t, bool flag) {//保持SBT树的性质
if (t==0) return;
if (!flag) {
if (T[T[T[t].l].l].s>T[T[t].r].s)
Right_Rotate(t);
else if (T[T[T[t].l].r].s>T[T[t].r].s)
Left_Rotate(T[t].l), Right_Rotate(t);
else return;
} else {
if (T[T[T[t].r].r].s>T[T[t].l].s)
Left_Rotate(t);
else if (T[T[T[t].r].l].s>T[T[t].l].s)
Right_Rotate(T[t].r), Left_Rotate(t);
else return;
}
Maintain(T[t].l, false);
Maintain(T[t].r, true);
Maintain(t, false);
Maintain(t, true);
}
void Insert(int &t, int key) {
if (t==0) {//插入结点
t = ++next;
T[t].init(key);
} else {
T[t].s ++;
if (key<T[t].key)
Insert(T[t].l, key);
else
Insert(T[t].r, key);
}
Maintain(t, key>=T[t].key);
}
//删除关键字为key的结点,没有该结点,删除搜索到最后的一个结点
int Delete(int &t, int key) {//删除就是一个覆盖的过程
T[t].s--;
if ((T[t].key==key)||(T[t].l==0 && key<T[t].key)||(T[t].r==0 && key>T[t].key)) {
int tmp = T[t].key;
if (T[t].l==0 || T[t].r==0)//用左儿子(或右儿子)覆盖该结点
t = T[t].l+T[t].r;
else//(T[t].key==key)时的情况用下面的结点覆盖该结点
T[t].key = Delete(T[t].l, T[t].key+1);
return tmp;//返回该结点原来的值
} else {
Delete(key<T[t].key?T[t].l:T[t].r, key);
}
}
int Find(int t, int key) {//查找并返回关键字为key的结点
if (t==0)
return 0;//不存在返回0
if (T[t].key==key)
return t;
else if (key<T[t].key)
return Find(T[t].l, key);
else
return Find(T[t].r, key);
}
//返回key在以t为根的树中的排名,也就是比key小的那颗树的size加一
int Rank(int t, int key) {
if (t==0)//key小于最小值时有问题
return 1;
else if (key==T[t].key)
return T[T[t].l].s+1;
else if (key>T[t].key)
return T[T[t].l].s+1+Rank(T[t].r, key);
else
return Rank(T[t].l, key);
}
//返回在第k位置上的结点,取最大值Select(t, T[t].s),最小值Select(t, 1)
int Select(int t, int k) {
if (k==T[T[t].l].s+1)
return T[t].key;
else if (k>T[T[t].l].s)
return Select(T[t].r, k-T[T[t].l].s-1);
else
return Select(T[t].l, k);
}
int Pred(int t, int key) {//返回比key小的最大的数
if (t==0)
return key;
if (key<=T[t].key)
return Pred(T[t].l, key);
else {
int tmp = Pred(T[t].r, key);
return tmp==key?T[t].key:tmp;
}
}
int Succ(int t, int key) {//返回比key大的最小的数
if (t==0)
return key;
if (key>=T[t].key)
return Succ(T[t].r, key);
else {
int tmp = Succ(T[t].l, key);
return tmp==key?T[t].key:tmp;
}
}
void Debug(int t) {
if (t==0)
return ;
Debug(T[t].l);
printf("%d ", T[t].key);
Debug(T[t].r);
}
NOI2004 郁闷的出纳员
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn = 2000000+10;
struct sbt {
int l, r, s, key;
void init(int k) {
l = r = 0, s = 1, key = k;
}
}T[maxn];
int next, root, n, ans, tmp, Min, d;
char s[11];
void init() {
next = root = 0;
tmp = ans = 0;
T[0].init(0);
T[0].s = 0;
}
void Right_Rotate(int &t) {
int k = T[t].l;
T[t].l = T[k].r;
T[k].r = t;
T[k].s = T[t].s;
T[t].s = T[T[t].l].s+T[T[t].r].s+1;
t = k;
}
void Left_Rotate(int &t) {
int k = T[t].r;
T[t].r = T[k].l;
T[k].l = t;
T[k].s = T[t].s;
T[t].s = T[T[t].l].s+T[T[t].r].s+1;
t = k;
}
void Maintain(int &t, bool flag) {
if (!flag) {
if (T[T[T[t].l].l].s>T[T[t].r].s)
Right_Rotate(t);
else if (T[T[T[t].l].r].s>T[T[t].r].s)
Left_Rotate(T[t].l), Right_Rotate(t);
else return ;
} else {
if (T[T[T[t].r].r].s>T[T[t].l].s)
Left_Rotate(t);
else if (T[T[T[t].r].l].s>T[T[t].l].s)
Right_Rotate(T[t].r), Left_Rotate(t);
else return ;
}
Maintain(T[t].l, false);
Maintain(T[t].r, true);
Maintain(t, false);
Maintain(t, true);
}
void Insert(int &t, int key) {
if (t==0) {
t = ++next;
T[t].init(key);
} else {
T[t].s++;
if (key<T[t].key)
Insert(T[t].l, key);
else
Insert(T[t].r, key);
}
Maintain(t, key>=T[t].key);
}
int Delete(int &t, int key) {
T[t].s--;
if ((T[t].key==key)||(T[t].l==0 & key<T[t].key)||(T[t].r==0 && key>=T[t].key)) {
int tmp = T[t].key;
if (T[t].l==0 || T[t].r==0)
t = T[t].l+T[t].r;
else
T[t].key = Delete(T[t].r, key);
return tmp;
} else {
if (key<T[t].key)
Delete(T[t].l, key);
else
Delete(T[t].r, key);
}
}
int Select(int t, int k) {
if (T[T[t].l].s+1==k) {
return T[t].key;
} else if (k<=T[T[t].l].s) {
return Select(T[t].l, k);
} else {
return Select(T[t].r, k-T[T[t].l].s-1);
}
}
void Debug(int t) {
if (t==0)
return ;
Debug(T[t].l);
printf("%d ", T[t].key);
Debug(T[t].r);
}
int main()
{
init();
cin >> n >> Min;
while (n--) {
scanf("%s%d", s, &d);
if (s[0]=='I') {
if (d>=Min) {
Insert(root, d-tmp);
}
} else if (s[0]=='A') {
tmp += d;
} else if (s[0]=='S') {
tmp -= d;
while (1) {
int qian = Select(root, 1);
if ((qian+tmp)<Min) {
Delete(root, qian);
ans ++;
} else break;
if (T[root].s==0)
break;
}
} else if (s[0]=='F') {
if (d>T[root].s) {
printf("-1\n");
} else {
printf("%d\n", Select(root, T[root].s-d+1)+tmp);
}
}
}
cout << ans << endl;
return 0;
}
HNOI2002 营业额统计
#include <iostream>
#include <cstdio>
using namespace std;
const int maxn = 1000000+10;
struct sbt {
int l, r, s, key;
void init(int k) {
l = r = 0, s = 1, key = k;
}
}T[maxn];
int next, root, n, data, ans;
void init() {
next = root = ans = 0;
T[0].init(0);
T[0].s = 0;
}
void Left_Rotate(int &t) {
int k = T[t].r;
T[t].r = T[k].l;
T[k].l = t;
T[k].s = T[t].s;
T[t].s = T[T[t].l].s+T[T[t].r].s+1;
t = k;
}
void Right_Rotate(int &t) {
int k = T[t].l;
T[t].l = T[k].r;
T[k].r = t;
T[k].s = T[t].s;
T[t].s = T[T[t].l].s+T[T[t].r].s+1;
t = k;
}
void Maintain(int &t, bool flag) {
//if (t==0)
// return ;
if (!flag) {
if (T[T[T[t].l].l].s>T[T[t].r].s)
Right_Rotate(t);
else if (T[T[T[t].l].r].s>T[T[t].r].s)
Left_Rotate(T[t].l), Right_Rotate(t);
else return ;
} else {
if (T[T[T[t].r].r].s>T[T[t].l].s)
Left_Rotate(t);
else if (T[T[T[t].r].l].s>T[T[t].l].s)
Right_Rotate(T[t].r), Left_Rotate(t);
else return ;
}
Maintain(T[t].l, false);
Maintain(T[t].r, true);
Maintain(t, false);
Maintain(t, true);
}
void Insert(int &t, int key) {
if (t==0) {
t = ++next;
T[t].init(key);
} else if (key<T[t].key) {
T[t].s++;
Insert(T[t].l, key);
} else {
T[t].s++;
Insert(T[t].r, key);
}
Maintain(t, key>=T[t].key);
}
int Succ(int t, int key) {
if (t==0)
return key;
if (key>=T[t].key) {
return Succ(T[t].r, key);
} else {
int tmp = Succ(T[t].l, key);
return tmp==key?T[t].key:tmp;
}
}
int Pred(int t, int key) {
if (t==0)
return key;
if (key<=T[t].key) {
return Pred(T[t].l, key);
} else {
int tmp = Pred(T[t].r, key);
return tmp==key?T[t].key:tmp;
}
}
int Find(int t, int key) {
if (t==0)
return 0;
else if (key==T[t].key) {
return 1;
} else if (key<T[t].key) {
return Find(T[t].l, key);
} else {
return Find(T[t].r, key);
}
}
void Debug(int t) {
if (t==0)
return;
Debug(T[t].l);
printf("%d ", T[t].key);
Debug(T[t].r);
}
inline int abs(int x) {
return x<0?(-x):x;
}
inline int Min(int x, int y) {
return x>y?y:x;
}
int main()
{
while (~scanf("%d", &n)) {
init();
for (int i=0; i<n; ++i) {
if(scanf("%d",&data)==EOF)data=0;
if (i==0) {
ans += data;
} else if (i==1) {
ans += abs(data-T[root].key);
} else {
if (Find(root, data)==0) {
int qian = Pred(root, data);
int hou = Succ(root, data);
if (qian==data) {
ans += abs(data-hou);
} else if (hou==data) {
ans += abs(data-qian);
} else {
ans += Min(abs(data-qian), abs(data-hou));
}
}
}
Insert(root, data);
}
cout << ans << endl;
}
return 0;
}