首页 > 其他分享 >谁都能学会的文艺平衡树

谁都能学会的文艺平衡树

时间:2022-11-15 23:57:31浏览次数:66  
标签:lazy val int siz 学会 文艺 tot inline 平衡

文艺平衡树

为什么要叫这个名字?因为翻转很文艺吗...

给你一个序列,每次进行区间翻转,要求最终得到的序列.

分析

正如它的名字一样,我们用FHQtreap来解决这个问题。

既然实现区间翻转了,那BST性质是否就被破坏掉了呢?

非也,还记得学习BST时我们提到了,二叉搜索树的中序遍历就是把序列从小到大排序的结果,

那么在这里就可以把顺序当作权值,维护这棵平衡树,从而实现区间操作。

具体怎么做呢?参照平衡树找第k小的做法,把顺序前l小(就是权值前l小)个元素分裂出来,

再从分裂出来的另一棵树中找到l到r的这部分分裂出来,再对这棵树进行操作就行了。

回到本题,要求的区间操作是翻转,把整棵树所有节点的左右儿子互换当然可以达到翻转的效果,但是复杂度达到了恐怖的O(n),这怎么能行?!

回想线段树区间修改的做法,对了!可以打上一个lazytag,这样在用上了的时候进行下传就可以了。

代码实现

#include<bits/stdc++.h>

using namespace std;
mt19937 rnd(233);
const int maxn=1e6 + 5;
struct node{
	int l,r,val,siz,key;
	bool lazy;
}f[maxn];
int root,tot;
inline int newnode(int val){
	f[++tot].val=val;
	f[tot].siz=1;
	f[tot].key=rnd();
	return tot;
}
inline void update(int p){
	f[p].siz=f[f[p].l].siz+f[f[p].r].siz+1;
}
inline void pushdown(int p){
	swap(f[p].l,f[p].r);
	f[f[p].l].lazy^=1;
	f[f[p].r].lazy^=1;
	f[p].lazy=0;
}
inline void split(int p,int size,int &x,int &y){
	if(!p)x=y=0;
	else {
		if(f[p].lazy)pushdown(p);
		if(f[f[p].l].siz<size){
			x=p;
			split(f[p].r,size-f[f[p].l].siz-1,f[p].r,y);
		}
		else {
			y=p;
			split(f[p].l,size,x,f[p].l);
		}
		update(p);
	}
}
inline int merge(int x,int y){
	if(!x||!y)return x+y;
	if(f[x].key<f[y].key){
		if(f[x].lazy)pushdown(x);
		f[x].r=merge(f[x].r,y);
		update(x);
		return x;
	}
	else {
		if(f[y].lazy)pushdown(y);
		f[y].l=merge(x,f[y].l);
		update(y);
		return y;
	}
}
void rev(int l,int r){
	int x,y,z;
	split(root,l-1,x,y);
	split(y,r-l+1,y,z);
	f[y].lazy^=1;
	root=merge(merge(x,y),z);
}
void ldr(int p){
	if(!p)return ;
	if(f[p].lazy)pushdown(p);
	ldr(f[p].l);
	printf("%d ",f[p].val);
	ldr(f[p].r);
}
inline int read(){
	int x=0,f=1;char ch=getchar();
	while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
	while(ch<='9'&&ch>='0'){x=x*10+ch-48;ch=getchar();}
	return x*f;
}
int main(){
	int n=read(),m=read();
	for(int i=1;i<=n;i++){
		root=merge(root,newnode(i));
	}
	for(int i=1;i<=m;i++){
		int l=read(),r=read();
		rev(l,r);
	}
	ldr(root);
}

写在后面

既然支持了区间操作和lazytag,那么这种平衡树就可以支持线段树的所有操作,甚至还有线段树不能实现的操作!但是常数略大略大...

标签:lazy,val,int,siz,学会,文艺,tot,inline,平衡
From: https://www.cnblogs.com/Hushizhi/p/16894482.html

相关文章

  • 项目资源管理从学会向上管理开始
    “如何一句话证明你当过项目经理?”这个话题在网上引发了广大项目管理人的兴趣,纷纷发表了个人看法(变相吐槽)。各种回答戳中笑点,同时也表达了作为项目经理的心酸。  l ......
  • 三秒让你学会公私网地址转换(NAT)
    NAT网络地址转换一.NAT定义二.华为Ensp拓扑图三.代码(动态NAT) 一.NAT定义NAT(NetworkAddressTranslasion) 又称网络地址转换,用于实现私有网络和公有网络之间的......
  • Hive查询的18种方式,你都学会了吗?
    持之以恒,贵在坚持,每天进步一点点!前言        大家一定对Hive不陌生吧!Hive是基于Hadoop的一个数据仓库工具,可以将结构化的数据文件映射为一张数据库表,并提供类SQL查......
  • 块状vector平衡树
    分块优化vector实现平衡树,当一个vector的大小超过定长的一半时将其分裂一半,删除时进行合并操作。但是,对于块长需要一定的人品,在数据范围1e6时,取sz=1000和1600可以,但是800......
  • 一文学会线程池、任务调度的使用
    一文学会线程池、任务调度的使用本文主要讲解线程池以及定时任务的使用,以及在分布式环境下、JUC线程池和Spring线程池的弊端。起因:分布式换环境下的定时任务问题❓......
  • 一文学会JavaScript计时事件
    文章目录​​JavaScript计时事件​​​​setInterval()方法​​​​clearInterval()方法​​​​setTimeout()方法​​​​clearTimeout()方法​​JavaScript计时事件......
  • 从头训练一个神经网络!教它学会莫奈风格作画!⛵
    ......
  • 一文学会,胶位偏移、缺胶、断胶、溢胶检测(含源码)
    检测任务点胶检查检测以下缺陷:1.缺少粘合胶的部分(断胶)2.粘合剂过多或过少的部分(溢胶、缺胶)3.粘合胶离其预定位置太远(点胶偏移)halcon对应示例程序:apply_bead_inspection_mode......
  • 判断语句Select Case,比If-Else语句的整洁,容易看懂的他,你只需1分钟就学会
    Hi,大家好,本专栏将会从零开始和大家用图文的方式,让你从零基础学会VBA!有兴趣的小伙伴可以持续关注我,或者在专栏进行查看学习,愿与君携手共进!在上一章节我们已经学习过如何使用I......
  • 数据不平衡问题的解决方案研究
    目标检测目前最困难的事情:漏检:无法把前景检测出来,个人认为,最简单的加数据解决误检:把背景检测为前景,也叫开放域识别问题。非常困难的事情。有人基于度量学习解决。主要......