算法笔记--可撤销并查集 && 可持久化并查集
可撤销并查集模板:
struct UFS {
stack<pair<int*, int>> stk;
int fa[N], rnk[N];
inline void init(int n) {
for (int i = 0; i <= n; ++i) fa[i] = i, rnk[i] = 0;
}
inline int Find(int x) {
while(x^fa[x]) x = fa[x];
return x;
}
inline void Merge(int x, int y) {
x = Find(x), y = Find(y);
if(x == y) return ;
if(rnk[x] <= rnk[y]) {
stk.push({fa+x, fa[x]});
fa[x] = y;
if(rnk[x] == rnk[y]) {
stk.push({rnk+y, rnk[y]});
rnk[y]++;
}
}
else {
stk.push({fa+y, fa[y]});
fa[y] = x;
}
}
inline void Undo() {
*stk.top().fi = stk.top().se;
stk.pop();
}
}ufs;
可持久化并查集模板:
struct Sustainable_DSU {
static const int N = 1e5 + 5, M = 2e6 + 5;
int root[N], lson[M], rson[M], fa[M], rnk[M], tot, n;
inline void build(int &rt, int l, int r) {
rt = ++tot;
if(l == r) {fa[rt] = l; return ;}
int m = l+r >> 1;
build(lson[rt], l, m);
build(rson[rt], m+1, r);
}
inline void init(int _n) {
n = _n;
tot = 0;
build(root[0], 1, n);
}
inline void Update(int old, int &rt, int p, int v, int l, int r) {
rt = ++tot;
lson[rt] = lson[old], rson[rt] = rson[old];
if(l == r) {
fa[rt] = v;
rnk[rt] = rnk[old];
return ;
}
int m = l+r >> 1;
if(p <= m) Update(lson[rt], lson[rt], p, v, l, m);
else Update(rson[rt], rson[rt], p, v, m+1, r);
}
inline void update(int rt, int p, int l, int r) {
if(l == r) { rnk[rt]++; return ;}
int m = l+r >> 1;
if(p <= m) update(lson[rt], p, l, m);
else update(rson[rt], p, m+1, r);
}
///返回rt版本p位置fa数组下标
inline int query(int rt, int p, int l, int r) {
if(l == r) return rt;
int m = l+r >> 1;
if(p <= m) return query(lson[rt], p, l, m);
else return query(rson[rt], p, m+1, r);
}
///返回rt版本p所在并查集fa数组下标
inline int Find(int rt, int p) {
int now = query(rt, p, 1, n);
if(fa[now] == p) return now;
else return Find(rt, fa[now]);
}
///在i时刻合并x和y所在并查集
inline void Merge(int i, int x, int y) {
root[i] = root[i-1];
int px = Find(root[i], x), py = Find(root[i], y);
if(fa[px] != fa[py]) {
if(rnk[px] > rnk[py]) swap(px, py);
Update(root[i-1], root[i], fa[px], fa[py], 1, n);
if(rnk[px] == rnk[py]) update(root[i], fa[py], 1, n);
}
}
};
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pli pair<LL, int>
#define pii pair<int, int>
#define piii pair<pii, int>
#define pdd pair<double, double>
#define mem(a, b) memset(a, b, sizeof(a))
#define debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head
struct Sustainable_DSU {
static const int N = 2e5 + 5, M = 4e6 + 5;
int root[N], lson[M], rson[M], fa[M], rnk[M], tot, n;
inline void build(int &rt, int l, int r) {
rt = ++tot;
if(l == r) {fa[rt] = l; return ;}
int m = l+r >> 1;
build(lson[rt], l, m);
build(rson[rt], m+1, r);
}
inline void init(int _n) {
n = _n;
tot = 0;
build(root[0], 1, n);
}
inline void Update(int old, int &rt, int p, int v, int l, int r) {
rt = ++tot;
lson[rt] = lson[old], rson[rt] = rson[old];
if(l == r) {
fa[rt] = v;
rnk[rt] = rnk[old];
return ;
}
int m = l+r >> 1;
if(p <= m) Update(lson[rt], lson[rt], p, v, l, m);
else Update(rson[rt], rson[rt], p, v, m+1, r);
}
inline void update(int rt, int p, int l, int r) {
if(l == r) { rnk[rt]++; return ;}
int m = l+r >> 1;
if(p <= m) update(lson[rt], p, l, m);
else update(rson[rt], p, m+1, r);
}
///返回rt版本p位置fa数组下标
inline int query(int rt, int p, int l, int r) {
if(l == r) return rt;
int m = l+r >> 1;
if(p <= m) return query(lson[rt], p, l, m);
else return query(rson[rt], p, m+1, r);
}
///返回rt版本p所在并查集fa数组下标
inline int Find(int rt, int p) {
int now = query(rt, p, 1, n);
if(fa[now] == p) return now;
else return Find(rt, fa[now]);
}
///在i时刻合并x和y所在并查集
inline void Merge(int i, int x, int y) {
root[i] = root[i-1];
int px = Find(root[i], x), py = Find(root[i], y);
if(fa[px] != fa[py]) {
if(rnk[px] > rnk[py]) swap(px, py);
Update(root[i-1], root[i], fa[px], fa[py], 1, n);
if(rnk[px] == rnk[py]) update(root[i], fa[py], 1, n);
}
}
}s;
int n, m, op, a, b;
int main() {
scanf("%d %d", &n, &m);
s.init(n);
for (int i = 1; i <= m; ++i) {
scanf("%d", &op);
if(op == 1) scanf("%d %d", &a, &b), s.Merge(i, a, b);
else if(op == 2) scanf("%d", &a), s.root[i] = s.root[a];
else {
scanf("%d %d", &a, &b);
s.root[i] = s.root[i-1];
a = s.Find(s.root[i], a);
b = s.Find(s.root[i], b);
if(s.fa[a] == s.fa[b]) printf("1\n");
else printf("0\n");
}
}
return 0;
}
算法笔记--可撤销并查集 && 可持久化并查集的更多相关文章
- 带撤销并查集 & 可持久化并查集
带撤销并查集支持从某个元素从原来的集合中撤出来,然后加入到一个另外一个集合中,或者删除该元素 用一个映射来表示元素和并查集中序号的关系,代码中用\(to[x]\) 表示x号元素在并查集中的 id 删除 ...
- [bzoj3673][可持久化并查集 by zky] (rope(可持久化数组)+并查集=可持久化并查集)
Description n个集合 m个操作 操作: 1 a b 合并a,b所在集合 2 k 回到第k次操作之后的状态(查询算作操作) 3 a b 询问a,b是否属于同一集合,是则输出1否则输出0 0& ...
- 【BZOJ3673/3674】可持久化并查集/可持久化并查集加强版 可持久化线段树
[BZOJ3674]可持久化并查集加强版 Description Description:自从zkysb出了可持久化并查集后……hzwer:乱写能AC,暴力踩标程KuribohG:我不路径压缩就过了! ...
- 【学习笔记】可持久化并查集(BZOJ3673)
好久之前就想学了 然后今天恰巧一道题需要用到就学了 前置芝士 1.主席树[可持久化数组] 2.并查集 如果你掌握了前面两个那么这个东西你就会觉得非常沙茶.. 构造 可持久化并查集 = 主席树 + 并 ...
- bzoj3674 可持久化并查集
我是萌萌的任意门 可持久化并查集的模板题-- 做法好像很多,可以标号法,可以森林法. 本来有O(mloglogn)的神算法(按秩合并+倍增),然而我这种鶸渣就只会写O(mlog2n)的民科算法--再加 ...
- [NOI2018]归程(可持久化并查集,Kruskal重构树)
解法一: 1.首先想到离线做法:将边和询问从大到小排序,并查集维护连通块以及每个连通块中所有点到1号点的最短距离.$O(n\log n)$ 配合暴力等可以拿到75分. 2.很容易想到在线做法,使用可持 ...
- kNN算法笔记
kNN算法笔记 标签(空格分隔): 机器学习 kNN是什么 kNN算法是k-NearestNeighbor算法,也就是k邻近算法.是监督学习的一种.所谓监督学习就是有训练数据,训练数据有label标好 ...
- 浅谈并查集&种类并查集&带权并查集
并查集&种类并查集&带权并查集 前言: 因为是学习记录,所以知识讲解+例题推荐+练习题解都是放在一起的qvq 目录 并查集基础知识 并查集基础题目 种类并查集知识 种类并查集题目 并查 ...
- 【BZOJ-3673&3674】可持久化并查集 可持久化线段树 + 并查集
3673: 可持久化并查集 by zky Time Limit: 5 Sec Memory Limit: 128 MBSubmit: 1878 Solved: 846[Submit][Status ...
随机推荐
- sql-获取重复和删除重复数据
//获取相同用户名的数据 //删除相同的数据,保留最大的id或者最小的id min(id) delete from user where id not in(select max(id) from u ...
- Navicat安装及使用
一.安装Navicat 1.下载安装文件:navicat11.0.17_premium_cs_x86.exe(32位) 2.Oracle 的 Instance Client:instantclient ...
- 游戏协议模拟测试工具(TcpEngine)使用简介
功能介绍 在有的网络开发需要走二进制流协议场景,比如网络游戏开发,在开发阶段,前端和后端协商好协议后就分别开发.在开发写代码的时候,有时需要对端发送一条完整的协议过来触发一下自己的代码,进行单步调试或 ...
- (CVE-2017-7494)Samba远程代码执行[Linux]
简介 此漏洞是针对开启了共享的smb服务 漏洞利用 启动msfconsole search is_known_pipename 搜索此模块 use exploit/linux/samba/is_k ...
- 最新 美团java校招面经 (含整理过的面试题大全)
从6月到10月,经过4个月努力和坚持,自己有幸拿到了网易雷火.京东.去哪儿.美团等10家互联网公司的校招Offer,因为某些自身原因最终选择了美团.6.7月主要是做系统复习.项目复盘.LeetCode ...
- 使用Homebrew来安装Node等工具
原文转载自:https://www.cnblogs.com/richard-youth/p/9718349.html 使用 React Native,必须安装的依赖有:Node.Watchman 和 ...
- WebStorm+Chrome调试Vue步骤
在调试时请 注意 : 在WebStorm中启动调试时,WebStorm会根据你设置的url,自动打开新的Chrome浏览器进程访问这个设置的url,而且这个浏览器页面和你平常看到的浏览器差异会比较大, ...
- shell将txt转换为csv
cat aa.txt | tr -s '[:blank:]' ',' > bb.csv
- [转帖]阿里云VS腾讯云 谁才是中国未来的云计算之王?
阿里云VS腾讯云 谁才是中国未来的云计算之王? https://www.qianzhan.com/analyst/detail/220/191008-f05009f6.html 吴小燕• 2019-1 ...
- C++:标准C函数(随机数,时间函数)
介绍 ANSI组织定义了C标准和标准库函数. 使用标准C函数优点: 使用标准C函数在任何平台上都支持,使得同一个源码,在Windows编译运行的结果和Linux上编译运行结果相同,无需更改代码. 随机 ...