首页 > 其他分享 >可撤销并查集学习笔记

可撤销并查集学习笔记

时间:2022-11-22 14:24:19浏览次数:85  
标签:log int 查集 撤销 fa 笔记 operatorname

前言

可持久化并查集 一起食用,效果更佳。

前置知识:并查集以及并查集的按秩合并优化。

例题引入

你需要维护一棵 \(n\) 个点的动态森林,初始时是 \(n\) 个散点,有 \(q\) 个操作,支持:

  • 1 u v,连边 \((u,v)\)。
  • 2 u v 查询 \(u,v\) 之间是否连通,连通输出 Yes,否则输出 No
  • 3 撤销上一个 \(1\) 操作。保证存在被撤销的操作。

\(1 \leq n,q \leq 2 \times 10^6\)

请大家想一想这一道题的 \(O(n+q\log n)\) 的 在线 做法。

思路

可持久化并查集?复杂度多一个 \(\log\)。

现在我给大家介绍一个 \(O(1)\) 撤销,\(O(\log n)\) 合并,\(O(\log n)\) 查连通性的并查集——可撤销并查集。

首先,我们需要确保每一次合并操作时只会修改常数次 \(\operatorname{fa}\) 数组,这样子才能保证时间复杂度。这就意味着,我们不能路径压缩(应为 \(\operatorname{fa}\) 数组修改次数期望 \(O(\log n)\),复杂度未保证)。所以我们只能按秩合并。这里使用子树大小 \(\operatorname{siz}\) 为秩。

然后,用两个栈来维护每一次合并时修改前的 \(\operatorname{fa}\) 和 \(\operatorname{siz}\) ,然后撤销的时后用栈顶来还原,最后弹栈即可。

参考代码

#include <bits/stdc++.h>
#define int long long
using namespace std;

int n,q;
int fa[20000005],siz[20000005];

struct UndoObject{
	int pos,val;
	UndoObject(int p,int v){
		pos=p,val=v;
	}
};

stack<UndoObject> undo_sz,undo_fa;

int find(int x){
	if(fa[x]==x)return x;
	else return find(fa[x]);
}

void merge(int u,int v){
	int x=find(u),y=find(v);
	if(x==y)return;
	if(siz[x]<siz[y]){
		swap(x,y);
	}
	undo_sz.push(UndoObject(x,siz[x]));
	siz[x]+=siz[y];
	undo_fa.push(UndoObject(y,fa[y]));
	fa[y]=x;
}

void undo(){
	fa[undo_fa.top().pos]=undo_fa.top().val;
	undo_fa.pop();
	siz[undo_sz.top().pos]=undo_sz.top().val;
	undo_sz.pop();
}

signed main(){
	ios::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL);
	cin>>n;
	for(int i=1;i<=n;i++){
		fa[i]=i;
		siz[i]=1;
	}
	cin>>q;
	while(q--){
		int op,u,v;
		cin>>op;
		if(op==1){
			cin>>u>>v;
			merge(u,v);
		}
		else if(op==2){
			cin>>u>>v;
			cout<<(find(u)==find(v)?"Yes":"No")<<'\n';
		}
		else{
			undo();
		}
	}
	return 0;
}

标签:log,int,查集,撤销,fa,笔记,operatorname
From: https://www.cnblogs.com/zheyuanxie/p/revocable-union-find.html

相关文章

  • Linux笔记
    Linux操作系统的开机过程:从BIOS开始,然后进入BootLoader,再加载系统内核,然后内核进行初始化,最后启动初始化进程RHEL7采用​​​systemd​​初始化进程服务。checkdate......
  • 操作系统笔记——重要概念
    操作系统基础概念​​操作系统​​​(OperatingSystem,OS)是指控制和管理整个计算机系统的硬件和软件资源,并合理地组织调度计算机的工作和资源的分配,以提供给用户和其他软件......
  • T292115 [传智杯 #5 练习赛] 树的变迁(并查集+倒序操作处理树分裂)
    T292115[传智杯#5练习赛]树的变迁题目大意:给定一棵具有\(n\)个节点的树,每个节点有一个初始权值\(a_i\)。一共需要进行\(m\)次操作,每次操作包括:1.1e编号......
  • React 学习笔记之一 - ES6 基础
    1.1let及const1.1.1let命令用var声明变量有变量提升的情况。1console.log(a);2vara=1; 如果没有第二行的声明,那么会看到“aisnotdefined......
  • 读书笔记·深入解析CSS·第二部分
    浮动设计初衷浮动能将一个元素拉到容器的一侧,这样文档流就能包围它。双容器模式用于将内容居中。通过将内容放在两个嵌套的容器中,然后给内层的容器设置外边距,让它在外......
  • Springcloud学习笔记52--通过ApplicationContextAware接口从spring上下文中获取到需要
    1.背景在spring项目中,bean之间的依赖关系是spring容器自动管理的,但是一个项目中有些类不在spring容器中却需要使用spring管理的bean,这时候不能通过正常的方式(注解等方式)......
  • IA-32汇编语言笔记(10)—— 子程序设计
    记录汇编语言课笔记,可能有不正确的地方,欢迎指出教材《新概念汇编语言》——杨季文这篇文章对应书第二章IA32处理器基本功能3.5部分文章目录​​一、子程序设计要点​​​......
  • git笔记(1)—— 基本操作
    文章目录​​1.git组织结构​​​​2.git基本操作​​​​3.分支管理​​1.git组织结构git由“工作区”和“版本库”组成,其中版本库由分为“暂存区”和“分支区......
  • NumPy笔记(2)—— 使用数组进行面向数组编程
    参考:《利用python进行数据分析》第4章注意,由于本文是jupyter文档转换来的,代码不一定可以直接运行,有些注释是jupyter给出的交互结果,而非运行结果!!文章目录​​1.生成网格数......
  • 使用vscode+evernote印象笔记+markdown写在线笔记
    1.vscode安装evermonkey插件2.vscode快捷键:Ctrl+Shift+P,输入ever按提示进行操作EverNew:创建新evernote笔记;愉快地玩耍点击下列图片标红位置,可以实时预览......