SBT

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;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值