首页 > 其他分享 >可持久化并查集

可持久化并查集

时间:2023-07-03 14:23:44浏览次数:33  
标签:ver val int 查集 tr rootfa rootdep 持久

因为这个版本感觉特别清楚就写个博客保留一下(
可持久化数组,都说是个数组了,那很多用数组维护的东西就都可以可持久化了。可持久化并查集,其实就是用主席树代替了原来的 \(fa\) 数组和 \(dep\) 数组,别的都是并查集的操作。注意不能写路径压缩,只能按秩合并,因为一旦路径压缩就可能会涉及到多个修改,复杂度就没有保证了(每次修改都得新开版本)。

模板代码,注释很详细。

//可!持!久!化!并!查!集!
//只要是树就都可以持久化是吧( 
#include<bits/stdc++.h>
using namespace std;
const int N = 2e5+10;
struct node
{
	int l, r, val; 
}tr[N*40*2];//这里相当于用一棵主席树干了两个树的活(只要把root存对问题都不大 
int idx, tot, rootfa[N], rootdep[N];//idx用来开点,tot用来赋值(初始fa)(啊好像没啥用,而且不太稳定。。。)
//tot这里有点多余w 
int n, m;

void build(int l, int r, int &u)
{
	u = ++idx;//开点 
	if(l==r) return tr[u].val = l, void();//相当于fa[i] = i; 
	int mid = (l+r)>>1;
	build(l, mid, tr[u].l);
	build(mid+1, r, tr[u].r);
}
//建树操作,因为fa要初始化,当然dep并不用
void modify(int l, int r, int ver, int &u, int pos, int val)//修改操作,相当于单点赋值 
{
	u = ++idx;
	tr[u] = tr[ver];//复制上一个版本,只对有修改的地方进行修改 ; 
	if(l == r) return tr[u].val = val, void();//递归到底,赋值; 
	int mid = (l+r)>>1;
	if(pos<=mid) modify(l, mid, tr[ver].l, tr[u].l, pos, val);
	else modify(mid+1, r, tr[ver].r, tr[u].r, pos, val);
}
int query(int l, int r, int u, int pos)
{
	if(l == r) return tr[u].val;//递归到底,取值,相当于取某个数组某下标对应的值 
	int mid = (l+r)>>1;
	if(pos<=mid) return query(l, mid, tr[u].l, pos);
	else return query(mid+1, r, tr[u].r, pos);
}
int find(int ver, int x)
{
	int fx = query(1, n, rootfa[ver], x);
	if(x!=fx) x = find(ver, fx);
	return x;
}

void merge(int ver, int x, int y)
{
	x = find(ver-1, x);//注意,这里的版本ver是更新后的版本 
	y = find(ver-1, y);//故应去版本ver中寻找 
	if(x == y)//发现本身已经合并,直接复制上一版本 
	{
		rootfa[ver] = rootfa[ver-1];
		rootdep[ver] = rootdep[ver-1];
	}
	else
	{
		int depx = query(1, n, rootdep[ver-1], x);
		int depy = query(1, n, rootdep[ver-1], y);//按秩合并——另一棵主席树来存储深度 
		if(depx<depy)
		{
			modify(1, n, rootfa[ver-1], rootfa[ver], x, y);//注意合并方向
			rootdep[ver] = rootdep[ver-1]; //深度不变,复制 
		}
		else if(depx>depy)
		{
			modify(1, n, rootfa[ver-1], rootfa[ver], y, x);
			rootdep[ver] = rootdep[ver-1];
		}
		else
		{
			modify(1, n, rootfa[ver-1], rootfa[ver], x, y);
			modify(1, n, rootdep[ver-1], rootdep[ver], y, depy+1);//还是方向问题 
		}
	}
 } 
int main()
{
	scanf("%d%d", &n, &m);
	build(1, n, rootfa[0]);//初始化fa“数组” 
	for(int i = 1; i<=m; i++)
	{
		int op, a, b;
		scanf("%d", &op);
		if(op == 1)
		{
			scanf("%d%d", &a, &b);
			merge(i, a, b);
			
		}
		else if(op == 2)
		{
			int k;
			scanf("%d", &k);
			rootfa[i] = rootfa[k];
			rootdep[i] = rootdep[k];
		}
		else
		{
			scanf("%d%d", &a, &b);
			rootfa[i] = rootfa[i-1];
			rootdep[i] = rootdep[i-1];
			a = find(i, a);
			b = find(i, b);
			if(a == b) puts("1");
			else puts("0");
		}
	}
	return 0;
}
//总结:就是并查集,就是并查集,就是并查集……
/*
操作一模一样,只是用主席树维护数组
将赋值操作变得有亿点点点麻烦
线段树来存储每个节点的父节点 
*/ 

标签:ver,val,int,查集,tr,rootfa,rootdep,持久
From: https://www.cnblogs.com/frostwood/p/17522771.html

相关文章

  • redis学习十五:redis持久化之AOF
    1.AOF是什么以日志的形式来记录每个写操作,将redis执行过的所有写指令记录下来(读操作不记录),redis重启的话会根据日志内容把指令从前到后执行一次来完成数据的恢复工作。默认情况,redis没有开启AOF更,开启功能需要设置appendonlyyes aof保存的是appendonly.aof文件2.AOF持久化......
  • IOS开发-NSUserDefaults的基本使用,缓存数据实现数据持久化
    NSUserDefaults是iOS与macOS中的一个存储对象。它用于存储应用程序运行期间和退出后需要保存的数据。NSUserDefaults的特点:-基于键值对:使用字符串作为键名存储数据。-支持的类型:NSString、NSNumber、NSDate、NSArray、NSDictionary等基本数据结构。-存储在本地:数据存储......
  • 并查集——传新闻
    并查集——传新闻在社交网络中,有n个用户在m个朋友群中相互交流。我们来分析一下在用户之间传播一些新闻的过程。最初,某个编号为x的用户收到新闻,随后他将新闻发送给他的朋友(如果两个人同属于一个或多个朋友群,则两者便是朋友)。而朋友们继续向他们的朋友发送新闻,以此类推,直至......
  • Redis中的事务与持久化简单整理
    Redis中的事务与持久化事务可以一次执行多个命令,并带有两个重要的保证:1、事务中的所有命令都被序列化并按顺序执行。Redis执行事务期间,不会被其它客户端发送的命令打断,事务中的所有命令都作为一个隔离操作顺序执行。2、Redis事务是原子操作,或者执行所有命令或者都不执行。通......
  • Redis持久化之 混合持久化
    Redis混合持久化什么是混合持久化混合持久化是在AOF持久化的基础上,定期进行RDB持久化,以保证数据的快速恢复混合持久化的实现方式是在AOF重写时,将RDB文件以二进制压缩格式写入到AOF文件的开头,之后的数据再以AOF格式追加到文件的末尾3混合持久化的优点是:可以减......
  • 第二天(redis基础,配置,事务,持久化(RDB,AOF),发表和订阅,主从复制,哨兵模式)
    LISTlremkeynvaluerpoplpushab把a的右边的元素加到b的左边Set集合从第一个集合移动到第二个集合Hash哈希Zset有序集合GEO地理位置(类似Hash)HyperloglogBitMapredis配置(pdf里)redis事务实践R......
  • [数据结构]笛卡尔树、ST表、带权并查集
    Cartesiantree(笛卡尔树)1.概念比如拿最小的当根建树,中序遍历是原数组2.性质区间最小值(RMQ),LCA的值,比如上图4和6的LCA是2,表示我们4,6,2这个区间里面的最小值是2找y左边第一个<=y的数就是y往上看第一个向左拐的数3.构造(增量法)对每个前缀考虑我们发现只有右链是......
  • RabbitMQ消息持久化
    我们看下之前启动idea测试消息发送的时候在后台生成的一条消息,现在已经在消息队列里面还没有被消费。 现在我们重启下RabbitMQ,执行linux命令:dockerrestartmq看上图实时显示的错误信息,失去连接了,接下来刷新这个页面,可以发现这个对象没有了。 说明rabbit消息并不会持久化,不......
  • Tomcat7 session 持久化
    tomcat7session默认是持久化的,tomcat7关闭或者重启,都会将内容持久化到SESSION.ser文件,这里推荐使用everything这个软件,查找这个文件。参考官方文档: 戳我......
  • Android性能优化:微信自用高性能持久化框架——MMKV组件原理
    MMKVMMKV——基于mmap的高性能通用key-value组件,底层序列化/反序列化使用protobuf实现,性能高,稳定性强。githubMMKV是基于mmap内存映射的移动端通用key-value组件,底层序列化/反序列化使用protobuf实现,性能高,稳定性强。从2015年中至今,在iOS微信上使用已有近3年,其......