首页 > 其他分享 >学习笔记:splay树(2)

学习笔记:splay树(2)

时间:2023-08-12 23:14:13浏览次数:31  
标签:学习 int tr 笔记 splay fa MAXN now 翻转

1.题目描述

传送门:here

大意:给你一个序列,让你每次翻转区间\([l,r]\),并且输出最后的区间

2.思路

1.暴力

每次暴力翻转区间 时间复杂度\(O(n^2)\) 妥妥T

2.平衡树

考虑怎么用splay实现

我们知道平衡树的特性:不管怎么树旋转 它的中序遍历一定是不变的 而且\(BST\)的中序遍历一定是从小到大的

思考如何利用这个性质

翻转区间是什么?

不就是在一段区间遍历中,从左根右变成右根左

这样折腾太麻烦,不如直接交换左右子树位置

怎么找到那一段区间的子树呢?

回忆一下是怎么删除节点的

把前驱翻转到根,后继翻转到根的右节点,那么根节点的右子树的左子树就是要找的点

同理,翻转区间\([l,r]\),我们把\(l-1\)翻转到根,把\(r+1\)翻转到右子树,此时左子树为对应区间

因为一开始直接给定了序列,可以一开始就建出一棵完美平衡树

同样要插入最小和最大

还有些优化就是为了减少时间复杂度打上懒标记

其他就没什么了

注意:此时满足的是编号的\(BST\) 而不是\(val\)的\(BST\)

Code:

#include<bits/stdc++.h>
#define MAXN 100005
using namespace std;
int n,m,a[MAXN];
int tot,root;
int size[MAXN],fa[MAXN],val[MAXN];
int tr[MAXN][2],lz[MAXN];
void Pushup(int x)
{
	size[x]=size[tr[x][0]]+size[tr[x][1]]+1;
}
void Pushdown(int x)
{
	if(!lz[x]) return;
	swap(tr[x][0],tr[x][1]);
	lz[tr[x][1]]^=1;
	lz[tr[x][0]]^=1;
	lz[x]=0;
}
int chk(int x)
{
	return tr[fa[x]][1]==x;
}
void rotate(int x)
{
	int y=fa[x],z=fa[y],k=chk(x),w=tr[x][k^1];
	tr[y][k]=w;fa[w]=y;
	tr[z][chk(y)]=x;fa[x]=z;
	tr[x][k^1]=y;fa[y]=x;
	Pushup(y);
	Pushup(x);
}
void splay(int x,int goal)
{
	while(fa[x]!=goal)
	{
		int y=fa[x];
		int z=fa[y];
		if(z!=goal)
			if(chk(x)^chk(y)) rotate(x);
			else rotate(y);
		rotate(x);
	}
	if(!goal) root=x;
}
int build(int l,int r,int f)
{
	if(l>r) return 0;
	int now=++tot;
	fa[now]=f;
	int mid=(l+r)/2;
	val[now]=a[mid];
	tr[now][0]=build(l,mid-1,now);
	tr[now][1]=build(mid+1,r,now);
	Pushup(now);
	return now;
}
int kth(int k)
{
	int now=root;
	while(1)
	{
		Pushdown(now);
		if(tr[now][0]&&k<=size[tr[now][0]])
			now=tr[now][0];
		else if(k>size[tr[now][0]]+1)
		{
			k-=size[tr[now][0]]+1;
			now=tr[now][1];
		}
		else
			return now;
	}
}
void print(int now)
{
	Pushdown(now);
	if(tr[now][0]) print(tr[now][0]);
	if(val[now]>=1&&val[now]<=n)cout<<val[now]<<" "; 
	if(tr[now][1]) print(tr[now][1]); 
}
int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0),cout.tie(0);
	cin>>n>>m;
	for(int i=1;i<=n+1;i++)
		a[i+1]=i;
	root=build(1,n+2,0);
	for(int i=1;i<=m;i++)
	{
		int l,r;
		cin>>l>>r;
		l=kth(l),r=kth(r+2);
		splay(l,0);
		splay(r,l);
		lz[tr[r][0]]^=1;
	}
	print(root);
	return 0;
}

标签:学习,int,tr,笔记,splay,fa,MAXN,now,翻转
From: https://www.cnblogs.com/g1ove/p/17625799.html

相关文章

  • 大疆无人机飞行技术学习笔记
    好的作品:飞行技术(手稳)+后期+创意+景色新手操作:自动起飞、降落手动起飞、降落空中刹停、一键返航(设置返航高度)镜头上下角度调整飞行模式:稳定、普通、运动拍照录像下一步学习:机械臂拍摄、延时摄影、跟踪......
  • 学习go语言编程之常量
    什么在常量在Golang中,常量是指在编译期就已知且不可改变的值。字面常量在程序中硬编码的常量值被称为字面常量,如:-12//整数类型常量3.1415926//浮点类型常量3.2+12i//复数类型常量true//布尔类型常量"foo"//字符串常量常量定义使用关键字con......
  • 学习go语言编程之数据类型
    数据类型概述Golang语言内置了如下基础数据类型:布尔类型:bool整型:int8,unit8,int16,uint16,int32,uint32,int64,uint64,int,uint,uintptr浮点类型:float32,float64复数类型:complex64,complex128字符串:string字符类型:rune错误类型:error同时,Golang还支持如下复合类型:指针:pointer数组......
  • 学习go语言编程之流程控制
    Golang支持如下4种流程控制语句:条件语句:if,else和elseif选择语句:switch,case和select循环语句:for,range跳转语句:goto条件语句示例代码:a:=3ifa<5{fmt.Println(a,"litterthan5")}else{fmt.Println(a,"notlitterthan5")}关于条件语句,要注意以下......
  • requests源码阅读笔记
    requests框架结构整个架构包括两部分:Session持久化参数和HTTPAdapter适配器连接请求,其余部分都是urllib3的内容。......
  • 萌新学习c语言记录
    这几天学了~等的符号使用还有如1>>2这种移动(二进制)方式(应该可以这么说)这几天学习的东西都是一点新东西和一部分复习之前学习的东西而且新东西有点难还有不用第三个变量来交换另外两个变量的方式(但这种方式运行的时候有些缓慢)如inta=3;intb=5;a=a^b;b=a^b;a=a^b;这样就可以了但......
  • springmvc学习之com.fasterxml.jackson.core:jackson-databind:pom:2.15.2 failed to
    -错误的原因是我们通过坐标依赖导入的jar包没有完全下载,也就是下载了一半就停了,是个下载类型的文件而不是真正的jar包,出现这种错误的原因典型的就比如我这种情况,正在下载的时候断网了,然后这个网络链接突然中断,此时文件就是一个损坏的半成品,Maven中的代码似乎不能像迅雷那样继续下......
  • SQL学习
    前言SQL,全称为StructuredQueryLanguage(结构化查询语言)数据库,一般就是指的 Relationaldatabase(关系型数据库),是用来存储大量数据的一种软件SQL是用来操作数据库里的数据,具体来说SQL可以做数据查询,数据更新,写入数据等等。......
  • 七月学习之Firewalld区域概念
    2、Firewalld区域概念相较于传统的iptables防火墙,firewalld支持动态更新,并加入了区域zone的概念2.1、什么是区域简单来说,区域就是firewalld预先准备了几套防火墙策略集合(策略模板),用户可以根据不同的场景而选择不同的策略模板,从而实现防火墙策略之间的快速切换专有网络(禁止访问G......
  • 学习笔记:反転魔法
    学习笔记:反転魔法1.反演是什么?反演这个词,意思是两个函数(当然也可以是数列一类的东西)的双向求和关系。比如已知\(f(i)=\sum\limits_{j=0}^{+\infty}A(i,j)\timesg(j)\),然后推出\(g(i)=\sum\limits_{j=0}^{+\infty}B(i,j)\timesf(j)\),这就是一对反演关系。那么反演......