平衡树(BST)
有关平衡树
说实话,好久没有打平衡树,现在手非常的生疏
所以时隔多年,我要重新捡起我的平衡树板子来,特此重新敲一遍
额,临时起意,我认为之前写的板子还挺符合我的心意的,我决定就用之前的了......
所以我就将几种平衡树写在这里
Splay
这个复杂度我也不会分析,好像是啥势能分析
反正没事就\(splay\)一下,就快起来了
code
struct node1{
int son[2],fa;
int siz,val,cnt;
}a[N*100];
int rt[N*4],seg;
int v[N],maxn;
struct Splay{
inline int get(int x){
return x==a[a[x].fa].son[1];
}
inline void pushup(int x){
a[x].siz=a[a[x].son[0]].siz+a[a[x].son[1]].siz+a[x].cnt;
}
void rotate(int x){
int y=a[x].fa,z=a[y].fa;
int xpos=get(x),ypos=get(y);
a[z].son[ypos]=x;
a[x].fa=z;
a[y].son[xpos]=a[x].son[xpos^1];
a[a[x].son[xpos^1]].fa=y;
a[x].son[xpos^1]=y;
a[y].fa=x;
pushup(y);
pushup(x);
}
void splay(int &root,int x,int goal){
while(a[x].fa!=goal){
int y=a[x].fa,z=a[y].fa;
int xpos=get(x),ypos=get(y);
if(z!=goal)
if(xpos==ypos)rotate(y);
else rotate(x);
rotate(x);
}
if(goal==0)root=x;
}
void ins(int &root,int x){
int u=root,fa=0;
while(u&&a[u].val!=x){
fa=u;
u=a[u].son[x>a[u].val];
}
if(u)a[u].cnt++;
else{
u=++seg;
if(fa)a[fa].son[x>a[fa].val]=u;
a[u].val=x;
a[u].siz=a[u].cnt=1;
a[u].fa=fa;
a[u].son[0]=a[u].son[1]=0;
}
splay(root,u,0);
}
void find(int &root,int x){
int u=root;
while(x!=a[u].val)
u=a[u].son[x>a[u].val];
splay(root,u,0);
}
void del(int &root,int x){
find(root,x);
if(a[root].cnt>1){
a[root].cnt--;
pushup(root);
return ;
}
if(!a[root].son[0]){
root=a[root].son[1];
pushup(root);
return ;
}
if(!a[root].son[1]){
root=a[root].son[0];
pushup(root);
return ;
}
int u=root;
u=a[u].son[0];
while(a[u].son[1])
u=a[u].son[1];
splay(root,u,root);
a[a[root].son[1]].fa=u;
a[u].son[1]=a[root].son[1];
a[a[root].son[0]].fa=0;
root=u;
pushup(root);
return ;
}
int getpre(int &root,int x){
ins(root,x);
int u=root;
u=a[u].son[0];
while(a[u].son[1])
u=a[u].son[1];
del(root,x);
return a[u].val;
}
int getnxt(int &root,int x){
ins(root,x);
int u=root;
u=a[u].son[1];
while(a[u].son[0])
u=a[u].son[0];
del(root,x);
return a[u].val;
}
}sp;
FHQ Treap
这个好说,因为随机出来的\(rnd\)可以保证这颗树是平衡的
这里是我的随机数
于是,我们只需要不断地掰开-插入-合并-掰开-删除-合并
code
int merge(int x,int y){
if(!x||!y)return x+y;
if(a[x].rnd>a[y].rnd){
a[x].r=merge(a[x].r,y);
pushup(x);
return x;
}
else{
a[y].l=merge(x,a[y].l);
pushup(y);
return y;
}
}
void split(int r,int pos,int &x,int &y){
if(!r){
x=y=0;
return ;
}
if(a[a[r].l].siz>=pos){
y=r;
split(a[r].l,pos,x,a[r].l);
pushup(r);
}
else{
x=r;
split(a[r].r,pos-a[a[r].l].siz-1,a[r].r,y);
pushup(r);
}
}
void ins(int &r,int pos,int val){
int x=0,y=0,z=0;
split(r,pos-1,x,y);
newnode(z,val);
r=merge(merge(x,z),y);
}
void del(int &r,int pos){
int x=0,y=0,z=0;
split(r,pos,x,z);
split(x,pos-1,x,y);
y=merge(a[y].l,a[y].r);
r=merge(merge(x,y),z);
}
还有这个放着当古董的Treap
这个真的不如无旋的好写,也不如无旋的好用,而且不能可持久化,说白了就是废物一个
code
#define lc a[x].l
#define rc a[x].r
const int N=100005;
int n;
struct node{
int l,r;
int val,dat;
int cnt,siz;
}a[N];
int seg,root;
int inf=0x3f3f3f3f;
int newdo(int val){
a[++seg].val=val;
a[seg].dat=rand();
a[seg].cnt=a[seg].siz=1;
return seg;
}
void pushup(int x){
a[x].siz=a[lc].siz+a[rc].siz+a[x].cnt;
}
void build(){
newdo(-inf);
newdo(inf);
root=1;
a[1].r=2;
pushup(root);
}
void zrg(int &x){
int q=a[x].l;
a[x].l=a[q].r;
a[q].r=x;
x=q;
pushup(rc);
pushup(x);
}
void zlg(int &x){
int q=a[x].r;
a[x].r=a[q].l;
a[q].l=x;
x=q;
pushup(lc);
pushup(x);
}
void insert(int &x,int val){
if(x==0){
x=newdo(val);
return ;
}
if(val==a[x].val){
a[x].cnt++;
pushup(x);
return ;
}
if(a[x].val>val){
insert(lc,val);
if(a[lc].dat>a[x].dat)zrg(x);
}
else{
insert(rc,val);
if(a[rc].dat>a[x].dat)zlg(x);
}
pushup(x);
}
int getpre(int val){
int ret=1;
int x=root;
while(x){
if(val==a[x].val){
if(a[x].cnt>1)return val;
if(lc>0){
x=lc;
while(rc>0)x=rc;
ret=x;
}
break;
}
if(val>a[x].val and a[x].val>a[ret].val)ret=x;
if(a[x].val>val)x=lc;
else x=rc;
}
return a[ret].val;
}
int getnxt(int val){
int ret=2;
int x=root;
while(x){
if(val==a[x].val){
if(a[x].cnt>1)return val;
if(rc>0){
x=rc;
while(lc>0)x=lc;
ret=x;
}
break;
}
if(a[x].val>val and a[ret].val>a[x].val)ret=x;
if(a[x].val>val)x=lc;
else x=rc;
}
return a[ret].val;
}
QQ:2953174821