首页 > 其他分享 >FHQ- Treap学习笔记

FHQ- Treap学习笔记

时间:2024-12-17 22:54:27浏览次数:5  
标签:ch 关键字 int 笔记 Treap 权值 FHQ

FHQ-Treap 与Treap都保证在第一关键字有序的情况下,维护第二关键字以达到平衡的目的。

但是Treap用的是旋转,FHQ-Treap 用的是分裂和合并。

  • FHQ-Treap 与Treap不同的地方:

    1. 优美的分裂和合并。
    2. 非旋。
    3. 支持区间修改
  • FHQ-Treap 与Treap相同的地方:

    1. 都保证在第一关键字有序的情况下,维护第二关键字。
    2. 本质上都是BST(二叉搜索树)。
  • 注意点

    1. 合并时要保证第一棵树的权值小于第二棵树的权值(因为合并操作只比较随机值)(仅指作为平衡树时的操作)。
    2. 排名分裂维护的是书的中序遍历。(例题)
  • Code of P3369 【模板】普通平衡树

#include<bits/stdc++.h>
#define N 200005
using namespace std;

inline int read(){
	int x=0,w=1;
	char ch=getchar();
	while(ch>'9'||ch<'0'){if(ch=='-')w=-1;ch=getchar();}
	while(ch>='0'&&ch<='9')x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
	return x*w;
}

int t,n,m,cnt,root;
bool flag[N];
struct node{int l,r,val,key,siz;}tree[N];

void push_up(int p){
	tree[p].siz=tree[tree[p].l].siz+1+tree[tree[p].r].siz;
}
int build_new(int x){
	tree[++cnt].siz=1;
	tree[cnt].val=x;
	tree[cnt].key=rand();
	return cnt;
}
int merge(int x,int y){
	if(!x||!y) return x+y;
	if(tree[x].key<tree[y].key){
		 tree[x].r=merge(tree[x].r,y);
		 push_up(x);
		 return x;
	}
	else{
		tree[y].l=merge(x,tree[y].l);
		push_up(y);
		return y;
	}
}
void split(int p,int k,int &x,int &y){
	if(!p) {
		x=y=0;
		return;
	}
	if(tree[p].val<=k) x=p,split(tree[p].r,k,tree[p].r,y);
	else y=p,split(tree[p].l,k,x,tree[p].l);
	push_up(p);
}
int kth(int p,int k){
	if(k<=tree[tree[p].l].siz) return kth(tree[p].l,k);
	else if(k==tree[tree[p].l].siz+1) return p;
	else return kth(tree[p].r,k-tree[tree[p].l].siz-1); 
}
signed main(){
	srand((unsigned)time(NULL));
	t=read();
	while(t--){
		int opt=read(),x=read();
		if(opt==1) {
			int a,b;
			split(root,x,a,b);
			root=merge(a,merge(build_new(x),b));
		}
		else if(opt==2) {
			int a,b,c;
			split(root,x,a,b);
			split(a,x-1,a,c);
			c=merge(tree[c].l,tree[c].r);
			root=merge(merge(a,c),b);
		}
		else if(opt==3){
			int a,b;
			split(root,x-1,a,b);
			printf("%d\n",tree[a].siz+1);
			root=merge(a,b);
		}
		else if(opt==4) printf("%d\n",tree[kth(root,x)].val);
		else if(opt==5){
			int a,b;
			split(root,x-1,a,b);
			printf("%d\n",tree[kth(a,tree[a].siz)].val);
			root=merge(a,b);
		}
		else{
			int a,b;
			split(root,x,a,b);
			printf("%d\n",tree[kth(b,1)].val);
			root=merge(a,b);
		}
	}
	return 0;
}
  • 关于可持久化

​ fhq_Treap 的可持久化和主席树类似,\(\log{N}\) 级别的。

​ 在进行split 新建节点即可,merge不用新建节点(大概)。

#include<bits/stdc++.h>
#define N 500005
using namespace std;

inline int read(){
	int x=0,w=1;
	char ch=getchar();
	while(ch>'9'||ch<'0'){if(ch=='-')w=-1;ch=getchar();}
	while(ch>='0'&&ch<='9')x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
	return x*w;
}

const int inf=2147483647;
int t,n,m,cnt;
int root[N];
struct node{int l,r,val,key,siz;}tree[N*50];

void push_up(int p){
	tree[p].siz=tree[tree[p].l].siz+1+tree[tree[p].r].siz;
}
int build_new(int x){
	tree[++cnt].siz=1;
	tree[cnt].val=x;
	tree[cnt].key=rand();
	return cnt;
}
int merge(int x,int y){
	if(!x||!y) return x+y;
	if(tree[x].key<tree[y].key){
		int p=++cnt;
		tree[p]=tree[x];
		tree[p].r=merge(tree[p].r,y);
		push_up(p);
		return p;
	}
	else{
		int p=++cnt;
		tree[p]=tree[y];
		tree[p].l=merge(x,tree[p].l);
		push_up(p);
		return p;
	}
}
void split(int p,int k,int &x,int &y){
	if(!p) {
		x=y=0;
		return;
	}
	if(tree[p].val<=k){
		x=++cnt;tree[x]=tree[p];	
		split(tree[x].r,k,tree[x].r,y);
		push_up(x);
	}
	else{
		y=++cnt;tree[y]=tree[p];
		split(tree[y].l,k,x,tree[y].l);
		push_up(y);
	}
}
int kth(int p,int k){
	if(k<=tree[tree[p].l].siz) return kth(tree[p].l,k);
	else if(k==tree[tree[p].l].siz+1) return p;
	else return kth(tree[p].r,k-tree[tree[p].l].siz-1); 
}
signed main(){
	srand((unsigned)time(NULL));
	t=read();
	for(int i=1;i<=t;++i){
		int used=read(),opt=read(),x=read();
		root[i]=root[used];
		if(opt==1) {
			int a,b;
			split(root[i],x,a,b);
			root[i]=merge(a,merge(build_new(x),b));
		}
		else if(opt==2) {
			int a,b,c;
			split(root[i],x,a,b);
			split(a,x-1,a,c);
			c=merge(tree[c].l,tree[c].r);
			root[i]=merge(merge(a,c),b);
		}
		else if(opt==3){
			int a,b;
			split(root[i],x-1,a,b);
			printf("%d\n",tree[a].siz+1);
			root[i]=merge(a,b);
		}
		else if(opt==4) printf("%d\n",tree[kth(root[i],x)].val);
		else if(opt==5){
			int a,b;
			split(root[i],x-1,a,b);
			if(!a) printf("%d\n",-inf);
			else {
				printf("%d\n",tree[kth(a,tree[a].siz)].val);
				root[i]=merge(a,b);
			}
		}
		else{
			int a,b;
			split(root[i],x,a,b);
			if(!b) printf("%d\n",inf);
			else {
				printf("%d\n",tree[kth(b,1)].val);
				root[i]=merge(a,b);
			}
		}
	}
	return 0;
}

其实就稍微改了一点东西。

  • 最后

FHQ-Treap 真是太阳间了!!!

FHQ YYDS


过了半年稍微有了点新的认识。

和大多数平衡数一样,是已每棵树都是一整个数列来维护的。

可以是权值的二叉搜索树,也可以是数列中排名的二叉搜索树。

这是一种极其灵活的数据结构,深刻了解才能熟练运用。

一些妙妙题

https://www.luogu.com.cn/problem/P3960

标签:ch,关键字,int,笔记,Treap,权值,FHQ
From: https://www.cnblogs.com/lxgswrz/p/18613592

相关文章

  • 树状数组学习笔记
    位运算是补码进行运算的因此可以解释负数进行位运算时的奇妙现象补码:正数的补码就是其本身负数的补码是在其原码的基础上,符号位不变,其余各位取反,最后+1.(即在反码的基础上+1)E:原码:10000001;补码:01111111.lowbit:lowbit这个函数的功能就是求某一个数的二进制表示......
  • 主席树学习笔记
    权值线段树就是指线段树的叶子节点保存的是当前值的个数。权值线段树一般支持以下三个操作:inserterase/removequery贴一个alphadalao的题解。主席树主席树,也叫做可持久化线段树,准确来说,应该叫做可持久化权值线段树,因为其中的每一颗树都是一颗权值线段树。经典例......
  • zkw线段树学习笔记
    先%一下zkw。stozkworzzkw线段树是一个改良版的线段树。其功能与传统线段树相同,也是用于维护区间信息。但是zkw线段树有很多优点:代码简短;纯天然非递归;常数小(尤其在差分区间更新时)特点:堆式储存,找父亲只需右移一位。建树和线段树一样,父节点左移一位为左儿子,再+1(或者|......
  • 奇绩创坛公开课第01课_创业走出第一步_陆奇:学习笔记
    写在前面背景:笔者已完整完成奇绩创坛官网上面的创业公开课,并且取得了结课证书。并且在2024年12月份参加了奇绩在我们学校的线下公开课。由于发现这些创业课程的质量很好,于是决定将学习笔记发布出来。一方面,对于学校里面的学生来说,这些经过萃取过的创业知识和方法论很有指......
  • Golang学习笔记_12——结构体
    Golang学习笔记_09——if条件判断Golang学习笔记_10——SwitchGolang学习笔记_11——指针文章目录结构体1.定义2.访问&&修改3.零值初始化&使用指针初始化4.匿名字段和嵌套结构体5.结构体方法和接收者源码结构体Go语言中的结构体(struct)是一种复合数据......
  • 代理 mitmproxy Python启动时,配置 block_global 参数,使用笔记(三)
    代理mitmproxyPython启动时,配置block_global参数,使用笔记(三)为什么要加block_global=false?,若不加,则只能本地拦截,而移动设备,或非本机请求时则无法被拦截将报错如下:Clientconnectionfrom192.167.6.166killedbyblock_globaloption注意:使用Python的非命令行启动,之前的......
  • 阅读笔记
    技术深度与广度在《程序员修炼之道》中,作者强调了程序员在技术深度和广度上的均衡发展。技术深度意味着对某一领域技术的深入理解和熟练掌握;而技术广度则要求程序员了解多个技术领域,以便在解决问题时能够灵活应用。深入掌握核心技能:书中提到,程序员应该深入掌握至少一种编程语言......
  • 【学习笔记总结】华为云:应用上云后的安全规划及设计
     一、背景和问题        数字化时代,随着信息技术的飞速发展,企业和各类组织纷纷将自身的应用程序迁移至云端。云计算凭借其诸多优势,如成本效益、可扩展性、灵活性以及便捷的资源共享等,已然成为了现代业务运营的重要支撑。    今年,我所在企业也将IT系统全面迁......
  • 【大模型智能客服背景下】知识图谱笔记
     【背景】        在数字化飞速发展的时代,客户服务的质量和效率成为企业立足市场、赢得客户信赖的关键因素之一。随着人工智能技术的不断革新,智能客服应运而生,为企业与客户之间搭建起了更为便捷、高效的沟通桥梁。        传统的智能客服系统往往基于预设规......
  • 弹性波动力学笔记(三) 应变张量简介上
    IntroductionofDeformation,StrainandRotationTensorsElasticitytheory,whichliesatthecoreofseismology,ismostgenerallystudiesasabranchofcontinuummechanics.Althoughthisgeneralapproachisnotrequiredinintroductorycourses,itisa......