SBT(Size Balance Tree), 即一种通过子树大小(size)保持平衡的BST

SBT的基本性质是:每个节点的size大小必须大于等于其兄弟的儿子的size大小:

当我们插入或者删除一个节点之后,SBT的性质会有所改变,此时需要函数maintain(mt)来维持平衡

mt(T)用于修复以T为根的子树的SBT 调用mt(T)的前提是T的子树都已经是SBT了

{由于左右对称,这里只讨论关于上图第一个不等式不成立的例子}

情形1:size[A] > size[R]

此时只需继续mt(A)与mt(L)就行

情形2:size[B] > size[R]

此时继续mt(L)与mt(B)

综上,Maintain代码如下:

  1. inline void update(node* r) { r->sz = r->lc->sz + r->rc->sz + 1; }
  2. void rotate(node* &r, bool f) {
  3. node *t = r->ch[f];
  4. r->ch[f] = t->ch[!f];
  5. t->ch[!f] = r;
  6. t->sz = r->sz;
  7. update(r);
  8. r = t;
  9. }
  10. void mt(node* &r, bool f) { //利用左右对称带上参数f同时减去不必要的检查
  11. if(r == NILL) return; //NILL 为空指针
  12. if(r->ch[f]->ch[f]->sz > r->ch[!f]->sz)
  13. rotate(r, f);
  14. else if(r->ch[f]->ch[!f]->sz > r->ch[!f]->sz)
  15. rotate(r->ch[f], !f), rotate(r, f);
  16. else return;
  17. mt(r->ch[f], f);
  18. mt(r, f);
  19. }

Analysis of Height

F[H]:高度为H最大结点个数,有定理:

F[H] = Fibonacci[H+2]-1

∴N个结点的SBT的最坏深度最大满足(F[H]<=N)的H,因此:

根据各种分析之后可得:Maintain的单次操作为O(1) SBT的其他操作时间复杂度都为为log(n)

所以SBT被称为目前最快的二叉平衡树!贴上模板题的代码(普通平衡树):

  1. #include <cstdio>
  2. #include <algorithm>
  3. using namespace std;
  4. #define lc ch[0]
  5. #define rc ch[1]
  6. const int MAXN = 500000;
  7. const int INF = 0x3f3f3f3f;
  8. struct node {
  9. node* ch[2];
  10. int sz, v;
  11. node(){}
  12. }SBT[MAXN+10], *NILL=new node, *root=NILL, *tot=SBT;
  13. int getint() {
  14. int ret = 0; bool f = 0; char ch;
  15. while((ch=getchar()) < '0' || ch > '9')if(ch == '-') f = !f;
  16. while(ch >= '0' && ch <= '9') ret = ret * 10 + ch - '0', ch = getchar();
  17. return f ? -ret : ret;
  18. }
  19. void init() {
  20. NILL->lc = NILL;
  21. NILL->rc = NILL;
  22. NILL->sz = 0;
  23. }
  24. inline void update(node* r) { r->sz = r->lc->sz + r->rc->sz + 1; }
  25. node* newnode() {
  26. tot->lc = tot->rc = NILL;
  27. tot->sz = 1;
  28. return tot++;
  29. }
  30. void rotate(node* &r, bool f) {
  31. node *t = r->ch[f];
  32. r->ch[f] = t->ch[!f];
  33. t->ch[!f] = r;
  34. t->sz = r->sz;
  35. update(r);
  36. r = t;
  37. }
  38. void mt(node* &r, bool f) {
  39. if(r == NILL) return;
  40. if(r->ch[f]->ch[f]->sz > r->ch[!f]->sz)
  41. rotate(r, f);
  42. else if(r->ch[f]->ch[!f]->sz > r->ch[!f]->sz)
  43. rotate(r->ch[f], !f), rotate(r, f);
  44. else return;
  45. mt(r->ch[f], f);
  46. mt(r, f);
  47. }
  48. void insert(node* &r, int v) {
  49. if(r == NILL) {
  50. r = newnode();
  51. r->v = v;
  52. return;
  53. }
  54. r->sz++;
  55. bool k = v > r->v;
  56. insert(r->ch[k], v);
  57. mt(r, k);
  58. }
  59. int del(node* &r, int x) {
  60. int ret;
  61. r->sz--;
  62. if(r->v == x || (r->lc == NILL && x < r->v) || (r->rc == NILL && x > r->v)) {
  63. ret = r->v;
  64. if(r->lc == NILL || r->rc == NILL)
  65. r = r->lc==NILL ? r->rc : r->lc;
  66. else r->v = del(r->lc, x);
  67. }
  68. else ret = del(r->ch[x>=r->v], x);
  69. return ret;
  70. }
  71. int sel(int val) {
  72. int ret = 1;
  73. node* p = root;
  74. while(p != NILL) {
  75. if(val <= p->v)
  76. p = p->lc;
  77. else {
  78. ret += p->lc->sz + 1;
  79. p = p-> rc;
  80. }
  81. }
  82. return ret;
  83. }
  84. int rk(int x)
  85. {
  86. node* p = root;
  87. while(p != NILL){
  88. if(x == p->lc->sz + 1)
  89. return p->v;
  90. if(x <= p->lc->sz)
  91. p = p->lc;
  92. else {
  93. x -= p->lc->sz + 1;
  94. p = p->rc;
  95. }
  96. }
  97. return INF;
  98. }
  99. int query(int v, bool f)
  100. {
  101. node* p = root;
  102. int ret = f ? INF : -INF;
  103. while(p != NILL) {
  104. if(p->v != v && (f == (p->v > v) && f == (ret > p->v)))
  105. ret = p->v;
  106. if(v == p->v)
  107. p = p->ch[f];
  108. else p = p->ch[v > p->v];
  109. }
  110. return ret;
  111. }
  112. int main () {
  113. init();
  114. int kase = getint();
  115. while(kase--) {
  116. int opt = getint(), x = getint();
  117. switch(opt) {
  118. case 1:insert(root, x); break;
  119. case 2:del(root, x); break;
  120. case 3:printf("%d\n", sel(x)); break;
  121. case 4:printf("%d\n", rk(x)); break;
  122. case 5:printf("%d\n", query(x, 0)); break;
  123. case 6:printf("%d\n", query(x, 1)); break;
  124. }
  125. }
  126. }

但可能还是没有avl快

初学 Size Balanced Tree(bzoj3224 tyvj1728 普通平衡树)的更多相关文章

  1. Size Balanced Tree(SBT) 模板

    首先是从二叉搜索树开始,一棵二叉搜索树的定义是: 1.这是一棵二叉树: 2.令x为二叉树中某个结点上表示的值,那么其左子树上所有结点的值都要不大于x,其右子树上所有结点的值都要不小于x. 由二叉搜索树 ...

  2. Size Balanced Tree

    Size Balanced Tree(SBT)是目前速度最快的平衡二叉搜索树,且能够进行多种搜索操作,区间操作:和AVL.红黑树.伸展树.Treap类似,SBT也是通过对节点的旋转来维持树的平衡,而相 ...

  3. C基础 - 终结 Size Balanced Tree

    引言 - 初识 Size Balanced Tree 最近在抽细碎的时间看和学习 random 的 randnet 小型网络库. iamrandom/randnet - https://github. ...

  4. Size Balanced Tree(SBT树)整理

    不想用treap和Splay,那就用SB树把,哈哈,其实它一点也SB,厉害着呢. 先膜拜一下作者陈启峰.Orz 以下内容由我搜集整理得来. 一.BST及其局限性 二叉查找树(Binary Search ...

  5. 子树大小平衡树(Size Balanced Tree,SBT)操作模板及杂谈

    基础知识(包括但不限于:二叉查找树是啥,SBT又是啥反正又不能吃,平衡树怎么旋转,等等)在这里就不(lan)予(de)赘(duo)述(xie)了. 先贴代码(数组模拟): int seed; int ...

  6. Size Balanced Tree(节点大小平衡树)

    定义 SBT也是一种自平衡二叉查找树,它的平衡原理是每棵树的大小不小于其兄弟树的子树的大小 即size(x->l)$\ge$size(x->r->l),size(x->r-&g ...

  7. [bzoj3224][tyvj1728][普通平衡树] (pb_ds库自带红黑树)

    Description 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作: 1. 插入x数 2. 删除x数(若有多个相同的数,因只删除一个) 3. 查询x数的排名(若有多个相 ...

  8. [Bzoj3224][Tyvj1728] 普通平衡树(splay/无旋Treap)

    题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=3224 平衡树入门题,学习学习. splay(学习yyb巨佬) #include<b ...

  9. [BZOJ3224/Tyvj1728]普通平衡树

    本篇博客有详细题解,浅谈算法--splay

随机推荐

  1. C++ 把数组数据存入 CSV 文件,以及读取 CSV 文件的数据

    1. CSV-百度百科 2. 代码 #pragma once //Microsoft Visual Studio 2015 Enterprise #include<iostream> #i ...

  2. 简单的python爬虫教程:批量爬取图片

    python编程语言,可以说是新型语言,也是这两年来发展比较快的一种语言,而且不管是少儿还是成年人都可以学习这个新型编程语言,今天南京小码王python培训机构变为大家分享了一个python爬虫教程. ...

  3. AS3放大镜工具类

    package { import flash.display.Bitmap; import flash.display.BitmapData; import flash.display.Display ...

  4. windows10环境下的RabbitMQ安装_笔记

    原文:https://blog.csdn.net/weixin_39735923/article/details/79288578 第一步:下载并安装erlang原因:RabbitMQ服务端代码是使用 ...

  5. AssemblyVersion、AssemblyFileVersion、AssemblyInformationalVersion 区别

    AssemblyVersion: 几乎保留在.NET内部,AssemblyFileVersion: 就是Windows所见.如果您转到位于目录中的程序集的属性并切换到版本选项卡, 映射到“文件版本”A ...

  6. Asp.Net进阶/值类型与引用类型:复习

    什么是值类型? 值类型: 就是非类类型,委托类型,接口类型,string类型的类型称为值类型. 引用类型类型:就是类类型,委托类型,接口类型,string类型称为引用类型. 值类型与引用类型的赋值问题 ...

  7. 在有多个网卡,配置了多个IP的情况下,python 获取本地网卡的主IP

    如图所示有多个网卡 本地网卡配置了多个IP class Public_IPOp: @staticmethod def GetLocalIP(): rt = [False] # 根节点 reg_root ...

  8. memcpy 速度测试

    1. 小米8代i5    3840X2160X4   7.77ms      即34Gbps

  9. Django:母版、继承、组件、自定义标签

    1.for循环应用 1.1for Variable Description forloop.counter 当前循环的索引值(从1开始) forloop.counter0 当前循环的索引值(从0开始) ...

  10. ios开发之NSData

    NSData用于保存字节数组. 初始化 - (instancetype)initWithBytesNoCopy:(void *)bytes length:(NSUInteger)length free ...