最近开始学习SBT,参考陈启峰的论文,具体的证明没有看,弱菜只是会用。。。
SBT有两条性质:
对于SBT中的每个结点t,有性质(a)(b):
(a). s[right[t]]≥s[left[left[t]]],s[right[left[t]]]
(b). s[left[t]]≥s[right[right[t]]],s[left[right[t]]]
即在上图中,有s[A],s[B]≤s[R]&s[C],s[D] ≤s[L]
可以参考下面的博客,平衡二叉树SBT
关于删除操作的说明:
与普通维护size域的BST删除相同。
关于无需Maintain的说明by sqybi:
在删除之前,可以保证整棵树是一棵SBT。当删除之后,虽然不能保证这棵树还是SBT,但是这时整棵树的最大深度并没有改变,所以时间复杂度也不会增加。这时,Maintain就显得是多余的了。
下面是模板:
struct SBT
{
int left,right,size,key;
void init(int val)
{
left=right=0;
size=1;
key=val;
}
}tree[maxn];
int tot,root;
void left_rotate(int &x)
{
int y=tree[x].right;
tree[x].right=tree[y].left;
tree[y].left=x;
tree[y].size=tree[x].size;
tree[x].size=tree[tree[x].left].size+tree[tree[x].right].size+1;
x=y;
}
void right_rotate(int &x)
{
int y=tree[x].left;
tree[x].left=tree[y].right;
tree[y].right=x;
tree[y].size=tree[x].size;
tree[x].size=tree[tree[x].left].size+tree[tree[x].right].size+1;
x=y;
}
void maintain(int &x,int flag)
{
if(!flag)
{
if(tree[tree[tree[x].left].left].size>tree[tree[x].right].size)
right_rotate(x);
else if(tree[tree[tree[x].left].right].size>tree[tree[x].right].size)
left_rotate(tree[x].left),right_rotate(x);
else return;
}
else
{
if(tree[tree[tree[x].right].right].size>tree[tree[x].left].size)
left_rotate(x);
else if(tree[tree[tree[x].right].left].size>tree[tree[x].left].size)
right_rotate(tree[x].right),left_rotate(x);
else return;
}
maintain(tree[x].left,0);
maintain(tree[x].right,1);
maintain(x,0);
maintain(x,1);
}
//插入值为key的节点
void insert(int &x,int key)
{
if(!x)
{
x=++tot;
tree[x].init(key);
}
else
{
tree[x].size++;
if(key<tree[x].key)insert(tree[x].left,key);
else insert(tree[x].right,key);
maintain(x,key>=tree[x].key);
}
}
//删除值为key的节点
int del(int &x,int key)
{
if(!x)return 0;
tree[x].size--;
if(key==tree[x].key||(key<tree[x].key&&tree[x].left==0)||
(key>tree[x].key&&tree[x].right==0))
{
if(tree[x].left&&tree[x].right)
{
int p=del(tree[x].left,key+1);
tree[x].key=tree[p].key;
return p;
}
else
{
int p=x;
x=tree[x].left+tree[x].right;
return p;
}
}
else
return del(key<tree[x].key?tree[x].left:tree[x].right,key);
}
//int del(int &x,int key)
//{
// if(!x)return 0;
// int res=0;
// tree[x].size--;
// if(key==tree[x].key||(key<tree[x].key&&tree[x].left==0)||
// (key>tree[x].key&&tree[x].right==0))
// {
// if(tree[x].left&&tree[x].right)
// {
// int p=del(tree[x].left,key+1);
// tree[x].key=tree[p].key;
// res=p;
// }
// else
// {
// int p=x;
// x=tree[x].left+tree[x].right;
// res=p;
// }
// }
// else
// res=del(key<tree[x].key?tree[x].left:tree[x].right,key);
// maintain(x,key<tree[x].key);
// return res;
//}
//返回值v的前驱的值,如果没有前驱返回v本身
int Pred(int t,int v)
{
if(!t)return v;
if(v<=tree[t].key)return Pred(tree[t].left,v);
else
{
int tmp=Pred(tree[t].right,v);
return v==tmp?tree[t].key:tmp;
}
}
//返回值v的后继的值,如果没有后继返回v本身
int Succ(int t,int v)
{
if(!t)return v;
if(v>=tree[t].key)return Succ(tree[t].right,v);
else
{
int tmp=Succ(tree[t].left,v);
return v==tmp?tree[t].key:tmp;
}
}
//返回值val的前驱的编号,没有的话,返回y
int get_pre(int &r,int y,int val)
{
if(r==0)return y;
if(val>tree[r].key)//加上等号就是大于等于
return get_pre(tree[r].right,r,val);
else return get_pre(tree[r].left,y,val);
}
//返回值val的后继的编号,没有的话,返回y
int get_next(int &r,int y,int val)
{
if(r==0)return y;
if(val<tree[r].key)return get_next(tree[r].left,r,val);
else return get_next(tree[r].right,y,val);
}
//查找是否存在值为val的节点
int find(int r,int val)
{
if(r&&val!=tree[r].key)
r=(val<tree[r].val?find(tree[r].left,val):find(tree[r].right,val));
return r;
}
//得到第k大元素的值
int get_kth(int &x,int k)
{
if(k<=tree[tree[x].left].size)
return get_kth(tree[x].left,k);
if(k>tree[tree[x].left].size+1)
return get_kth(tree[x].right,k-tree[tree[x].left].size-1);
return tree[x].key;//改一下就可以返回节点编号了
}
//返回根为x的树最大值的编号
int get_max(int x)
{
while(tree[x].right)x=tree[x].right;
return x;
}
//返回根为x的树最小值的编号
int get_min(int x)
{
while(tree[x].left)x=tree[x].left;
return x;
}
//返回值val的排名
int get_rank(int &r,int val)
{
if(val<tree[r].val)
return get_rank(tree[r].left,val);
else if(val>tree[r].val)
return get_rank(tree[r].right,val)+tree[tree[r].left].size+1;
return tree[tree[r].left].size+1;
}