首页 > 其他分享 >splay

splay

时间:2023-10-13 21:55:57浏览次数:31  
标签:la int void 旋转 splay 节点

splay 是一种能支持区间操作的平衡树。

建树:

struct splay_tree{
	int f,c[2],cnt,size,val,la;//父亲、儿子、节点数量、子树大小、节点权值、懒标记
}t[N];

pushup 和 pushdown 操作:

void pushup(int p)
{
	t[p].size=t[t[p].c[0]].size+t[t[p].c[1]].size+t[p].cnt;
}
void pushdown(int p)
{
	swap(t[p].c[0],t[p].c[1]);
	t[p].la=0;
	t[t[p].c[0]].la^=1,t[t[p].c[1]].la^=1;//异或,因为翻转两次等于没翻
}

旋转操作:

图片

void rotate(int x)//将x与它的父亲旋转
{
	int y=t[x].f;// x的父亲
	int z=t[y].f;// x的祖宗
	int d=t[y].c[1]==x; //x为y的那个儿子
	t[z].c[t[z].c[1]==y]=x;//将 x接的y的位置上
	t[x].f=z;//更新x的父亲
	t[y].c[d]=t[x].c[d^1];//接下来和treap差不多,不过还要维护父亲节点
	t[t[x].c[d^1]].f=y;
	t[x].c[d^1]=y;
	t[y].f=x;
	pushup(y);//先y后x
	pushup(x);
}

splay 操作:

旋转的时候有两种情况:

图片1 图片2

第一种需先旋转y,第二种需先旋转x

然后都需旋转x,才能完成操作。

void splay(int x,int k)//将x旋转到k节点以(若k=0,即旋至根节点)
{
	while(t[x].f!=k){//转到k节点以下
		int y=t[x].f;
		int z=t[y].f;
		if(z!=k){//不能转到k节点
			if(!((t[z].c[1]==y)^(t[y].c[1]==x)))rotate(y);//分类讨论两种情况
			else rotate(x);
		}
		rotate(x);
	}
	if(k==0)root=x;//更新root
}

之后玄学的就来了。

我们每次插入一个值,都要把该值对应的节点splay到根节点。

这样就能保证复杂度为 $\log n $ ,证明就不是人能看懂的东西。总之splay操作有效避免了毒瘤的迫害(一条链)。

插入值 \(x\)

void insert(int x)
{
	int u=root,f=0; //从根节点向下找,同时记录父亲
	while(u&&t[u].val!=x){
		if(t[u].la)pushdown(u);//pushdown
		f=u;
		u=t[u].c[t[u].val<x];
	}
	if(u)t[u].cnt++;
	else{
		u=++idx;
		if(f)t[f].c[t[f].val<x]=u;//不能漏
		t[u].f=f;//不能漏
		t[u].val=x;
		t[u].size=t[u].cnt=1;
	}
	splay(u,0);//旋至根节点
}

找到值为 \(k\) 的节点。

int get_u(int k)
{
	int u=root;
	if(t[u].size<k)return 0;
	while(1){
		if(t[u].la)pushdown(u);//pushdown
		int y=t[u].c[0];
		if(t[y].size+1<k){
			k=k-t[y].size-1;//到右子树,k要减去相应的值
			u=t[u].c[1];
		}
		else{
			if(t[y].size+1>k)u=y;
			else return u;
		}
	}
}

区间操作:

处理节点 \(l\) 到 \(r\) 之间

spaly(l,0);
spaly(r+2,l);//有哨兵
solve(tr[r+1].ch[0])

标签:la,int,void,旋转,splay,节点
From: https://www.cnblogs.com/lzaqwq/p/17763340.html

相关文章

  • Splay
    prologue快csps了还什么也不会的一条费鱼。下面是分别通过acwingy总和樱雪喵学到的splay。introduction首先来了解一下二叉搜索树。二叉搜索树是一种二叉树的树形数据结构,其定义如下:空树是二叉搜索树。若二叉搜索树的左子树不为空,则其左子树上所有点的附加权值均小于......
  • display:none和overflow:hidden的区别
    1、display:none当将一个元素的display属性设置为none时,该元素将不会显示在网页中,并且不会占据任何空间。也就是说,该元素会完全隐藏,其他的元素会立即占据它原来的位置。该属性适用于需要完全隐藏某个元素的场景。//html代码:完全隐藏子元素<divclass="father"><di......
  • Go - Parsing Time Displays Into Structs
     funcmain(){str:="4:31am+0800onOct1,2021"layout:="3:04pm-0700onJan2,2006"t,err:=time.Parse(layout,str)iferr!=nil{log.Println("C......
  • display none 和 opacity 0 二者的区别辨析
    HTML属性display:none和opacity:0在Accessibility(无障碍性)处理上有明显的区别,它们分别用于不同的场景,并对网页元素的可见性和交互性产生不同的影响。在本文中,我将详细解释这两个属性的作用、区别以及何时使用它们,并提供示例来说明它们的效果。display:none和opacity:0......
  • jQuery中hide()和display的区别在于它们实现元素隐藏的方式不同。
    1.hide()方法是jQuery提供的一个函数,用于隐藏元素。当使用hide()方法时,元素会被设置为display:none,即不显示在页面上,但仍然占据着原来的空间。隐藏后的元素可以通过调用show()方法来重新显示。示例代码:$("#elementId").hide();//隐藏元素$("#elementId").show();//显示......
  • 比较 opacity: 0、visibility: hidden、display: none
    结构display:none:会让元素完全从渲染树中消失,渲染的时候不占据任何空间,不能点击,visibility:hidden:不会让元素从渲染树消失,渲染元素继续占据空间,只是内容不可见,不能点击opacity:0:不会让元素从渲染树消失,渲染元素继续占据空间,只是内容不可见,可以点击继承display:none和op......
  • display: none与visibility: hidden的区别
    display:none与visibility:hidden的区别引言:在前端面试中,一般比较侧重JavaScript方面的考察,CSS布局方面考察的内容会相对少一些,其中display:none与visibility:hidden的区别是较常见的考点,这两个css配置都可以从视觉上隐藏DOM元素,那这两者的使用上有什么区别呢?display:none......
  • 17 display 和 浮动
    display可以使得行内元素和块元素相互转换,但不常用,用float!<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><title>Title</title><style>/*inline:block:i......
  • python报错:pyglet.canvas.xlib.NoSuchDisplayException: Cannot connect to "None"
    运行python代码报错:       问题发现:问题其实十分的狗血,这个代码是在服务器上运行的,运行之前其实并没有看具体的代码情况,gitclone下载下来就直接运行了,原来这个代码需要进行图片绘制,说直白些就是需要显示屏,于是解决方法也十分简单,就是换个带桌面的电脑或者使用......
  • Python中的​​display​​​函数 from IPython.display import display
    Python中的display函数通常与JupyterNotebook或其他交互式开发环境一起使用,用于显示各种类型的数据,包括文本、图像、音频、视频等。这个函数通常是由IPython.display模块提供的,主要用于创建富媒体输出,以便在笔记本中直观地呈现数据。以下是有关display函数的一些重要信息:导入模块:......