【模板】【P3402】可持久化并查集
(题面来自洛谷)
题目描述
n个集合 m个操作
操作:
1 a b 合并a,b所在集合
2 k 回到第k次操作之后的状态(查询算作操作)
3 a b 询问a,b是否属于同一集合,是则输出1否则输出0
\(n \le 10^5, m \le 2\times 10^5\)
考虑不带路径压缩、使用启发式合并的并查集,每一次合并实际上只是改变了两个点的信息。
1. v的父亲置为u
2. \(size(u) += size(v)\)
那么将数组fa、size改为可持久化数组维护即可。
复杂度分析:根据启发式合并性质,每次Find操作会执行\(logn\)次循环,循环中为可持久化数组查询,故Find操作的单次复杂度为\(O(log^2n)\)。
代码:
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
typedef long long LL;
const int maxn(200010);
int n, m;
struct Seg_tree {
#define mid ((l + r) >> 1)
#define lc(nd) seg[nd].lc
#define rc(nd) seg[nd].rc
struct node {
int dat, lc, rc;
/* node(int a = 0, int b = 0, int c = 0):
dat(a), lc(b), rc(c) {}*/
// node(): dat(0), lc(0), rc(0) {}
} seg[maxn * 40];
int root[maxn], tot;
void modify(int& nd, int pre, int l, int r, int pos, int x) {
nd = ++tot;
seg[nd] = seg[pre];
if (l == r) {
seg[nd] = (node) {x, 0, 0};
return;
}
if (pos <= mid) modify(lc(nd), lc(pre), l, mid, pos, x);
else modify(rc(nd), rc(pre), mid+1, r, pos, x);
}
void build(int &nd, int l, int r, int val) {
nd = ++tot;
if (l == r) {
seg[nd] = (node) {val, 0, 0};
return;
}
build(lc(nd), l, mid, val);
build(rc(nd), mid+1, r, val);
return;
}
int query(int nd, int l, int r, int pos) {
if (!nd) return 0;
if (l == r) return seg[nd].dat;
if (pos <= mid) return query(lc(nd), l, mid, pos);
return query(rc(nd), mid+1, r, pos);
}
} Dsu, Siz;
int Find(int x, int ver) {
int tmp;
while (tmp = Dsu.query(Dsu.root[ver], 1, n, x)) x = tmp;
return x;
}
inline void merge(int u, int v, int ver) {
u = Find(u, ver), v = Find(v, ver);
if (u == v) return;
int a, b;
if ((a = Siz.query(Siz.root[ver], 1, n, u)) < (b = Siz.query(Siz.root[ver], 1, n, v))) swap(u, v);
Dsu.modify(Dsu.root[ver], Dsu.root[ver-1], 1, n, v, u);
Siz.modify(Siz.root[ver], Siz.root[ver-1], 1, n, u, a + b);
return;
}
int main() {
// freopen("test.in", "r", stdin);
// freopen("test.ans", "w", stdout);
scanf("%d %d", &n, &m);
Siz.build(Siz.root[0], 1, n, 1);
int op, u, v;
for (int i = 1; i <= m; ++i) {
scanf("%d %d", &op, &u);
if (op == 1) {
Siz.root[i] = Siz.root[i-1];
Dsu.root[i] = Dsu.root[i-1];
scanf("%d", &v);
merge(u, v, i);
} else if (op == 2) {
Siz.root[i] = Siz.root[u];
Dsu.root[i] = Dsu.root[u];
} else {
Siz.root[i] = Siz.root[i-1];
Dsu.root[i] = Dsu.root[i-1];
scanf("%d", &v);
putchar(Find(u, i) == Find(v, i) ? '1' : '0');
putchar('\n');
}
}
return 0;
}
【模板】【P3402】可持久化并查集的更多相关文章
- bzoj3673 & bzoj3674 & 洛谷P3402 可持久化并查集
题目:bzoj3673:https://www.lydsy.com/JudgeOnline/problem.php?id=3673 bzoj3674:https://www.lydsy.com/Jud ...
- 「luogu3402」【模板】可持久化并查集
「luogu3402」[模板]可持久化并查集 传送门 我们可以用一个可持久化数组来存每个节点的父亲. 单点信息更新和查询就用主席树多花 一个 \(\log\) 的代价来搞. 然后考虑如何合并两个点. ...
- 洛谷P3402 【模板】可持久化并查集 [主席树,并查集]
题目传送门 可持久化并查集 n个集合 m个操作 操作: 1 a b 合并a,b所在集合 2 k 回到第k次操作之后的状态(查询算作操作) 3 a b 询问a,b是否属于同一集合,是则输出1否则输出0 ...
- 【洛谷 P3402】 【模板】可持久化并查集
题目链接 可持久化并查集,就是用可持久化线段树维护每个版本每个节点的父亲,这样显然是不能路径压缩的,否则我们需要恢复太多状态. 但是这并不影响我们启发式合并,于是,每次把深度小的连通块向深度大的上并就 ...
- 洛谷P3402 可持久化并查集
n个集合 m个操作 操作: 1 a b 合并a,b所在集合 2 k 回到第k次操作之后的状态(查询算作操作) 3 a b 询问a,b是否属于同一集合,是则输出1否则输出0 说是可持久化并查集,实际上是 ...
- 洛谷P3402 【模板】可持久化并查集(可持久化线段树,线段树)
orz TPLY 巨佬,题解讲的挺好的. 这里重点梳理一下思路,做一个小小的补充吧. 写可持久化线段树,叶子节点维护每个位置的fa,利用每次只更新一个节点的特性,每次插入\(logN\)个节点,这一部 ...
- P3402 可持久化并查集
P3402 通过主席树维护不同版本的并查集,注意要采用按秩合并的方式,路径压缩可能会爆. 1 #include <bits/stdc++.h> 2 using namespace std; ...
- P3402 【模板】可持久化并查集
传送门 //minamoto #include<bits/stdc++.h> using namespace std; #define getc() (p1==p2&&(p ...
- 洛谷P3402 【模板】可持久化并查集
一定注意每一次都要是 $root[cur]=root[cur-1]$,不然进行合并时如果 $a,b$ 在同一集合中就会使 $root[cur]=0$. Code: #include <cstdi ...
- Luogu3402【模板】可持久化并查集 (主席树)
用\(depth\)按秩合并,不能直接启发,数组开40倍左右 #include <iostream> #include <cstdio> #include <cstrin ...
随机推荐
- Django model总结(上)
Django model是django框架中处于比较核心的一个部位,准备分三个博客从不同的方面分别进行阐述,本文为<上篇>,主要对[a]Model的基本流程,比如它的创建,迁移等:默认行为 ...
- kubectl命令小妙招
kubectl命令使用大全 中文: http://docs.kubernetes.org.cn/683.html [root@master-test ~]# kubectl --help kube ...
- 【新阁教育】穷学上位机系列——搭建STEP7仿真环境
经常有学员问我,学习上位机要不要买PLC硬件? 我一般的回答是:富则自行购买,穷则搭建仿真. PLC硬件,对于学习上位机来说,是锦上添花的事,经济条件允许,有则更好,条件不允许,我们也可以通过搭建仿真 ...
- 写文档太麻烦,试试这款 IDEA 插件吧!
前言 每次开发完新项目或者新接口功能等,第一件事就是提供接口文档.说到接口文档,当然是用 Markdown 了.各种复制粘贴字段,必填非必填,字段备注,请求返回示例等等.简直是浪费时间哇.所以想到了开 ...
- 第一行代码中RecyclerView添加依赖库问题
现在更新到 implementation 'com.android.support:recyclerview-v7:29.2.1' 记得点Sync Now来进行同步.
- 解决Python参考文档乱码问题
问题如下: 解决方案: 打开IE浏览器,随便输入一个网址,在页面空白处点击右键->编码->自动选择 再次重新开启python3 帮助文档即可
- 基于C++语言实现机动车违章处罚管理系统
这篇文章主要介绍了基于C++语言实现机动车违章处罚管理系统的相关资料,需要的朋友可以参考下 关键代码如下所示: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 ...
- 也谈模块加载,吐槽CMD
先吐槽CMD,不要没头没脑的搞出个CMD,没意思. 大家都看AMD好了,异步模块加载机制,CMD并没有改变这个模式. 模块加载的关口就是getCurrentScript,每次define被调用的时候, ...
- 基于CPU版本的Caffe推理框架
最近一段时间,认真研究了一下caffe.但是,里面内容过多,集合了CPU版本和GPU版本的代码,导致阅读起来有些复杂.因此,特意对caffe代码进行了重构,搭建一个基于CPU版本的Caffe推理框架. ...
- CSS3之flex布局
若要使用flex布局,需在父元素上声明" display : flex ",这样它所有的直系子元素就成为flex元素 1.居中 1)垂直居中:align-items : cente ...