平衡树(包括FHQ与Splay)

无旋treap(FHQ)

基本操作

新建

int New(int val)
{
	tot++;
	v[tot].val=val;
	v[tot].rnd=rand();
	v[tot].size=1;
	return tot;
}

分裂

void split(int rt,int val,int &x,int &y)
{
	if(!rt)
	{
		x=y=0;
		return;
	}
	if(v[rt].val<=val)
	{
		x=rt;
		split(rson,val,rson,y);
	}
	else
	{
		y=rt;
		split(lson,val,x,lson);
	}
	pushup(rt);
}

合并

int merge(int x,int y)
{
	if(!x||!y) return x+y;
	if(v[x].rnd<v[y].rnd)
	{
		v[x].rs=merge(v[x].rs,y);
		pushup(x);
		return x;
	}
	else
	{
		v[y].ls=merge(x,v[y].ls);
		pushup(y);
		return y;
	}
}

插入

void insert(int x)
{
	int y,z;
	split(root,x,y,z);
	root=merge(merge(y,New(x)),z);
}

删除

void del(int x)
{
	int y,z,q;
	split(root,x,y,z);
	split(y,x-1,y,q);
	q=merge(v[q].ls,v[q].rs);
	root=merge(merge(y,q),z);
}

第K大

int Kth(int rt,int k)
{
	while(1)
	{
		if(k<=v[lson].size) rt=lson;
		else if(k==v[lson].size+1) return v[rt].val;
		else
		{
			k-=(v[lson].size+1);
			rt=rson;
		}
	}
}

前驱/后继

int pre(int x)
{
	int y,z;
	split(root,x-1,y,z);
	int ret=Kth(y,v[y].size);
	root=merge(y,z);
	return ret;
}
int bck(int x)
{
	int y,z;
	split(root,x,y,z);
	int ret=Kth(z,1);
	root=merge(y,z);
	return ret;
}

区间操作(以翻转为例)

void pushup(int rt)
{
	v[rt].size=v[lson].size+v[rson].size+1;
}
void pushdown(int rt)
{
	if(!rt||!v[rt].lazy) return;
	swap(lson,rson);
	v[lson].lazy^=1;
	v[rson].lazy^=1;
	v[rt].lazy=0;
}
void split(int rt,int k,int &x,int &y)
{
	if(!rt)
	{
		x=y=0;
		return;
	}
	pushdown(rt);
	if(k>v[lson].size)
	{
		x=rt;
		k-=v[lson].size+1;
		split(rson,k,rson,y);
	}
	else
	{
		y=rt;
		split(lson,k,x,lson);
	}
	pushup(rt);
}
int merge(int x,int y)
{
	if(!x||!y) return x+y;
	if(v[x].rnd<v[y].rnd)
	{
		pushdown(x);
		v[x].rs=merge(v[x].rs,y);
		pushup(x);
		return x;
	}
	else
	{
		pushdown(y);
		v[y].ls=merge(x,v[y].ls);
		pushup(y);
		return y;
	}
}
void reverse(int l,int r)
{
	int x,y,z;
	split(root,r,x,y);
	split(x,l-1,x,z);
	v[z].lazy^=1;
	root=merge(merge(x,z),y);
}
void output(int rt)
{
	if(!rt) return;
	pushdown(rt);
	output(lson);
	cout<<v[rt].val<<" ";
	output(rson);
}

splay

关键点

辅助操作

bool dir(int x)
{
    return x==v[v[x].fa].ch[1];
}
void pushup(int rt)
{
    v[rt].siz=v[rt].cnt+v[v[rt].ch[0]].siz+v[v[rt].ch[1]].siz;
}

旋转伸展

void rotate(int x)
{
    int y=v[x].fa;
    int z=v[y].fa;
    bool r=dir(x);
    v[y].ch[r]=v[x].ch[!r];
    v[x].ch[!r]=y;
    if(z) v[z].ch[dir(y)]=x;
    if(v[y].ch[r]) v[v[y].ch[r]].fa=y;
    v[y].fa=x;
    v[x].fa=z;
    pushup(y);
	pushup(x);
}
void splay(int &z,int x)
{
    int w=v[z].fa,y=v[x].fa;
	while(y!=w)
	{
		if(v[y].fa!=w) rotate(dir(x)==dir(y)?y:x);
		rotate(x);
		y=v[x].fa;
	}
    z=x;
}

其它

void find(int &z,int val)
{
    if(!z) return;
    int x=z,y=z;
    while(x&&v[x].val!=val)
    {
        y=x;
        x=v[x].ch[val>v[x].val];
    }
    splay(z,x?x:y);
}
void loc(int &z,int k)
{
    int x=z;
    while(1)
    {
        if(v[v[x].ch[0]].siz>=k) x=v[x].ch[0];
        else if(v[v[x].ch[0]].siz+v[x].cnt>=k) break;
        else
        {
            k-=v[v[x].ch[0]].siz+v[x].cnt;
            x=v[x].ch[1];
        }
    }
    splay(z,x);
}
int Kth(int k)
{
    if(k>v[root].siz) return -1;
    loc(root,k);
    return v[root].val;
}
int merge(int x,int y)
{
    if(!x||!y) return x+y;
    loc(y,1);
    v[y].ch[0]=x;
    v[x].fa=y;
    pushup(y);
    return y;
}
void insert(int val)
{
    int x=root,y=0;
    while(x&&v[x].val!=val)
    {
        y=x;
        x=v[x].ch[val>v[x].val];
    }
    if(x) ++v[x].cnt,++v[x].siz;
    else
    {
        x=++tot;
        v[x].val=val;
        v[x].cnt=1;
        v[x].siz=1;
        v[x].fa=y;
        if(y) v[y].ch[val>v[y].val]=x;
    }
    splay(root,x);
}
bool del(int val)
{
    find(root,val);
    if(!root||v[root].val!=val) return false;
    v[root].cnt--,v[root].siz--;
    if(!v[root].cnt)
    {
        int x=v[root].ch[0],y=v[root].ch[1];
        v[x].fa=v[y].fa=0;
        root=merge(x,y);
    }
    return true;
}
int findsize(int val)
{
    find(root,val);
    return v[v[root].ch[0]].siz+(v[root].val<val ?v[root].cnt:0)+1;
}
int pre(int val)
{
    find(root,val);
    if(root&&v[root].val<val) return v[root].val;
    int x=v[root].ch[0];
    if(!x) return -1;
    while(v[x].ch[1]) x=v[x].ch[1];
    splay(root,x);
    return v[x].val;
}
int bck(int val)
{
    find(root,val);
    if(root&&v[root].val>val) return v[root].val;
    int x=v[root].ch[1];
    if(!x) return -1;
    while(v[x].ch[0]) x=v[x].ch[0];
    splay(root,x);
    return v[x].val;
}

FHQ可持久化

在分裂合并时加上克隆操作即可

int colne(int rt)
{
  v[++tot]=v[rt];
  return tot;
}
posted @ 2026-07-14 21:28  wang7979  阅读(4)  评论(2)    收藏  举报