可撤销并查集模板:

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);
}
}
};

P3402 【模板】可持久化并查集

代码:

#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;
}

算法笔记--可撤销并查集 && 可持久化并查集的更多相关文章

  1. 带撤销并查集 & 可持久化并查集

    带撤销并查集支持从某个元素从原来的集合中撤出来,然后加入到一个另外一个集合中,或者删除该元素 用一个映射来表示元素和并查集中序号的关系,代码中用\(to[x]\) 表示x号元素在并查集中的 id 删除 ...

  2. [bzoj3673][可持久化并查集 by zky] (rope(可持久化数组)+并查集=可持久化并查集)

    Description n个集合 m个操作 操作: 1 a b 合并a,b所在集合 2 k 回到第k次操作之后的状态(查询算作操作) 3 a b 询问a,b是否属于同一集合,是则输出1否则输出0 0& ...

  3. 【BZOJ3673/3674】可持久化并查集/可持久化并查集加强版 可持久化线段树

    [BZOJ3674]可持久化并查集加强版 Description Description:自从zkysb出了可持久化并查集后……hzwer:乱写能AC,暴力踩标程KuribohG:我不路径压缩就过了! ...

  4. 【学习笔记】可持久化并查集(BZOJ3673)

    好久之前就想学了 然后今天恰巧一道题需要用到就学了 前置芝士 1.主席树[可持久化数组] 2.并查集 如果你掌握了前面两个那么这个东西你就会觉得非常沙茶.. 构造 可持久化并查集 = 主席树  + 并 ...

  5. bzoj3674 可持久化并查集

    我是萌萌的任意门 可持久化并查集的模板题-- 做法好像很多,可以标号法,可以森林法. 本来有O(mloglogn)的神算法(按秩合并+倍增),然而我这种鶸渣就只会写O(mlog2n)的民科算法--再加 ...

  6. [NOI2018]归程(可持久化并查集,Kruskal重构树)

    解法一: 1.首先想到离线做法:将边和询问从大到小排序,并查集维护连通块以及每个连通块中所有点到1号点的最短距离.$O(n\log n)$ 配合暴力等可以拿到75分. 2.很容易想到在线做法,使用可持 ...

  7. kNN算法笔记

    kNN算法笔记 标签(空格分隔): 机器学习 kNN是什么 kNN算法是k-NearestNeighbor算法,也就是k邻近算法.是监督学习的一种.所谓监督学习就是有训练数据,训练数据有label标好 ...

  8. 浅谈并查集&种类并查集&带权并查集

    并查集&种类并查集&带权并查集 前言: 因为是学习记录,所以知识讲解+例题推荐+练习题解都是放在一起的qvq 目录 并查集基础知识 并查集基础题目 种类并查集知识 种类并查集题目 并查 ...

  9. 【BZOJ-3673&3674】可持久化并查集 可持久化线段树 + 并查集

    3673: 可持久化并查集 by zky Time Limit: 5 Sec  Memory Limit: 128 MBSubmit: 1878  Solved: 846[Submit][Status ...

随机推荐

  1. 最新 字节跳动java校招面经 (含整理过的面试题大全)

    从6月到10月,经过4个月努力和坚持,自己有幸拿到了网易雷火.京东.去哪儿.字节跳动等10家互联网公司的校招Offer,因为某些自身原因最终选择了字节跳动.6.7月主要是做系统复习.项目复盘.Leet ...

  2. 华为eNSP上的NAT地址转换配置

    NAT是将IP数据报文报头中的IP地址转换为另一个IP地址的过程,主要用于实现内部网络(私有IP地址)访问外部网络(公有IP地址)的功能. 1.实验拓扑 地址表: 1.完成各个接口基本配置之后使用pi ...

  3. python计算平面的法向-利用协方差矩阵求解特征值和特征向量

    Obvious,最小特征值对应的特征向量为平面的法向 这个问题还有个关键是通过python求协方差矩阵的特征值和特征向量,np.linalg.eig()方法直接返回了特征值的向量和特征向量的矩阵 sc ...

  4. windows下 安装gitlab及其相关图形管理工具

    windows下 安装gitlab及其相关图形管理工具   在windows下安装git中文版客户端并连接gitlab   下载git Windows客户端 git客户端下载地址:https://gi ...

  5. Nginx 开发者文档翻译 - 介绍

    由于我的一个Private Cloud FaaS(函数计算)项目 Navagraha 使用nginx作为实现Service Mesh和API Gateway的基础框架,需要对Nginx有深入的了解,因 ...

  6. Demonstration(CodeForces-191B)【贪心】

    题目链接:https://vjudge.net/problem/CodeForces-191B 题意:过于繁琐,略 思路:真·神级贪心题 首先我们可以想到的是,为了在k天内选到最靠前的城市,我们要想办 ...

  7. Python习题006

    作业一:打印10*10  星星 ★☆ 要求一:普通打印★ l = 0 while l <10: h = 0 while h < 9: print("★", end=&q ...

  8. docker系列3--dockerd配置文件

    dockerd启动配置 docker通信方式选择 docker默认以sock文件方式提供接口,要开放tcp接口远程调用,需要修改配置文件: The Docker daemon can listen f ...

  9. MySQL 字段类型介绍

    MySQL 基础篇 三范式 MySQL 军规 MySQL 配置 MySQL 用户管理和权限设置 MySQL 常用函数介绍 MySQL 字段类型介绍 MySQL 多列排序 MySQL 行转列 列转行 M ...

  10. Jenkins 2017年用过

    Jenkins是一个开源软件项目,是基于Java开发的一种持续集成工具,用于监控持续重复的工作,旨在提供一个开放易用的软件平台,使软件的持续集成变成可能. Jenkins功能包括: 1.持续的软件版本 ...