可撤销并查集模板:

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. 不使用局部变量和for循环或其它循环打印出如m=19,n=2結果为2 4 8 16 16 8 4 2形式的串

    需求:不使用局部变量和for循环或其它循环打印形如:2 4 8 16 16 8 4 2 这样的串 代码MainTest.java package com.szp.study.javase.specia ...

  2. 修改jira数据库配置

  3. css3 float排序问题

    css3 float排序问题 有时候发现 会错位 那是因为有个图片大小不一致才会这样 所以要确保每个图片一样

  4. Nachos java版学习(一)

    最近,操作系统课程设计使用伯克利大学的Nachos做为实验平台,老师也照搬伯克利的Project要求,开始我们的操作系统课程设计. 结合自己的学习过程和课设要求,我觉得对Nachos的学习首先应该从K ...

  5. wordpress 图片上传时发生了错误,请稍后再试 的解决办法

    前一天网站还是好好的,仅一天过后就显示图片无法上传,百思不得其解 上下百度,大多数帖子提供的解决办法对我都不适用,继续搜,最后发现一篇帖子中提到是wp-config的编码格式问题 想到昨天刚好修改了下 ...

  6. python之文件读写操作笔记

    对不同类的文件操作,需要调用相关的库文件,一般情况下,可以选择建立:写文件函数和读文件函数.在写文件与读文件函数中 我们可以采用:with  open('文件名','w', encoding='utf ...

  7. scratch少儿编程第一季——07、人要衣装佛靠金装——外观模块

    各位小伙伴大家好: 上期我们学习了如何设置背景,和设计一个小项目总结了动作模块. 本期开始我们学习外观模块下的指令. 首先我们来看看前面两个指令 第一个指令是在角色对象上出现一个对话框,显示角色所说的 ...

  8. Docker容器日志查看与清理的方法

    Docker容器日志查看与清理的方法 Docker 容器是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux机器上,也可以实现虚拟化.容器 ...

  9. Unity UGUI动态生成控件

    一. 首先你得先清楚RectTransform组件的一些程序控制 1. 先得到UGUI控件上面的RectTransform组件 RectTransform rtr = gameObject.GetCo ...

  10. (七)Activiti之历史活动查询和历史任务查询和流程状态查询

    一.历史活动查询 本章案例是基于上一章节案例的基础上,流程走完后进行测试的,也就是下图的流程从学生请假到班主任审批都已经完成,本章用来测试查询历史活动和历史任务的 activiti5的历史活动包括所有 ...