Splay

13 篇文章 1 订阅
5 篇文章 0 订阅
这篇博客介绍了一种名为‘文艺平衡树’的数据结构,它在插入和查找操作中表现出色。作者通过C++代码展示了如何构建和操作这种平衡树,包括旋转、展开和插入函数。在一系列示例中,平衡树被用于快速处理区间操作,优化了效率。博客还提醒读者注意代码中的一处细节,理解思路后问题迎刃而解。
摘要由CSDN通过智能技术生成

文艺平衡树

#include<iostream>
#include<cstdio>
#define N 100000
#define push_up(x) t[x].size=t[t[x].son[0]].size+t[t[x].son[1]].size+1
using namespace std;
int n,m,l,r,root,tot;
struct node
{
	int size,son[2],mark,val,pre;
	void init(int x,int fa)
    {
      son[0]=son[1]=0;
	  size=1,val=x,pre=fa;  	
	}
	
}t[N+1];
void push_up(int x)
{
    t[x].size=t[t[x].son[0]].size+t[t[x].son[1]].size+1;
}
void push_down(int x)
{
	if(t[x].mark)
	{
		t[x].mark=0;
		t[t[x].son[0]].mark^=1;
		t[t[x].son[1]].mark^=1;
		swap(t[x].son[1],t[x].son[0]);
	}
}
void spin(int x)
{
    int y=t[x].pre;
    int z=t[y].pre;
    int k=t[y].son[1]==x;
    t[z].son[t[z].son[1]==y]=x;
    t[x].pre=z;
    t[y].son[k]=t[x].son[k^1];
    t[t[x].son[k^1]].pre=y;
    t[x].son[k^1]=y;
    t[y].pre=x;
    push_up(y),push_up(x);
}
void splay(int x,int loc)
{
	while(t[x].pre!=loc)
	{
		int y=t[x].pre;
		int z=t[y].pre;
		if(z!=loc) (t[z].son[1]==y)^(t[y].son[1]==x)?spin(x):spin(y);
		spin(x);
	}
	if(loc==0) root=x;
}
void ins(int x)
{
	int s=root,ff=0;
	while(s) ff=s,s=t[s].son[x>t[s].val];
	s=++tot;
	if(ff) t[ff].son[x>t[ff].val]=s;
	t[s].init(x,ff);
	splay(s,0);
}
int get_rank(int x)
{
	int s=root;
	while(1)
	{
		push_down(s);
        if(t[t[s].son[0]].size>=x) s=t[s].son[0];
        else if(t[t[s].son[0]].size+1==x) return s;
        else x-=t[t[s].son[0]].size+1,s=t[s].son[1];
	}
}
void write(int u)
{
    push_down(u);
    if(t[u].son[0]) write(t[u].son[0]);
    if(t[u].val>1&&t[u].val<N-2) printf("%d ",t[u].val-1);
    if(t[u].son[1]) write(t[u].son[1]);
}
inline void work(int l,int r)
{
    l=get_rank(l);
    r=get_rank(r+2);
    splay(l,0);
    splay(r,l);
    t[t[t[root].son[1]].son[0]].mark^=1;
}
int main()
{
    scanf("%d%d",&n,&m);

    for(int i=1;i<=n+2;i++) ins(i); 
    
   while(m--)
    {
    	scanf("%d%d",&l,&r);
    	work(l,r);
	}
	write(root);
	printf("\n");
    return 0;
}

请勿copy,有一处小坑。理解了思路显而易见。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值