【模板】【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 ...
随机推荐
- 随便聊一聊&最近做的项目
好久没有发文章了,我并非闲着,而是把原来发博文的形式转成了写稿. 今年是非常特殊的一年,长这么大,从来没有休过如此漫长的寒假,也从未在家进行过一个月以上的远程办公,新冠肺炎对各行各业都产生了巨大影响, ...
- GoSDK的安装及环境变量配置 入门详解 - 精简归纳
GoSDK的安装及环境变量配置 入门详解 - 精简归纳 JERRY_Z. ~ 2020 / 10 / 29 转载请注明出处!️ 目录 GoSDK的安装及环境变量配置 入门详解 - 精简归纳 一.进入G ...
- 【译】Rust中的array、vector和slice
原文链接:https://hashrust.com/blog/arrays-vectors-and-slices-in-rust/ 原文标题:Arrays, vectors and slices in ...
- vite + ts 快速搭建 vue3 项目 以及介绍相关特性
博客地址:https://ainyi.com/98 Vue3.0,One Piece 接下来得抽空好好学习了 vite 尤大在 Vue 3.0 beta 直播中推荐了 vite 的工具,强调:针对Vu ...
- GANSS 87C键盘在Linux无法正常使用的解决办法
前几天在狗东入手可以一把GANSS的87C键盘,满心欢喜拆开来用却发现在开发电脑(Deepin和ubuntu)上F1-F12都不能正常使用,这对一个搞web开发的人来说,无疑是要了我的老命,无奈找各种 ...
- css 两边宽度固定中间自适应宽度
#content_left{ //左 width:73px; height:100px; vertical-align:middle; margin-right:-100px; float:lef ...
- 【SpringBoot】11.Springboot整合SpringMVC+Mybatis(上)
Springboot整合SpringMVC+Mybatis 需求分析:通过使用Springboot+SpringMVC+Mybatis 整合实现一个对数据库表users表的CRUD操作. 1.创建项目 ...
- HTML5+CSS3 QQ会员页面导航
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" ...
- 鸿蒙开发板外设控制 之 实现按键“按下事件”和“释放事件”的通用框架(V0.0.1)
在帖子 <鸿蒙开发板外设控制>直播图文版(2020.10.28) 中我们提到过:"开发板上的按键也可以看作一种 GPIO 外设." 因此,要捕捉按键的状态(按下或释放) ...
- HTML页面通过JS跨域调用,子传父
父页面:a.html 代码: <html> <head> <script type="text/javascript"> function te ...