算法笔记--可撤销并查集 && 可持久化并查集
可撤销并查集模板:
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 ...
随机推荐
- 【ARM-Linux开发】Rico Board上编译USB WiFi RT3070驱动
1.附件中提供了RT3070驱动源码包DPO_RT5572_LinuxSTA_2.6.1.3_20121022.tar.gz和编译好的驱动,这里选择使用taget_file.tar.gz中已经编译好的 ...
- php csv 简单的导入
if($act == 'user_upload_do'){ global $db; $filename = $_FILES['file']['tmp_name']; if (empty ($filen ...
- rewrite重写基础实列
nginx 重写 rewrite 基础及实例 nginx rewrite 正则表达式匹配 大小写匹配 ~ 为区分大小写匹配 ~* 为不区分大小写匹配 !~和!~*分别为区分大小写不匹配及不区分大小写不 ...
- python lanbda匿名函数(20)
在python开发中常规的函数在调用之前都需要先声明,而python还有一种匿名函数,有速写函数的功能并且匿名函数不需要声明也没有函数名字,完全不需要担心函数名冲突,具体的妙用还需要从实战练习中多多积 ...
- Asp.Net Core 客户端验证和远程验证
我们先来看这样一个注册页面和它的后台Model @model RegisterViewModel @{ ViewBag.Title = "用户注册"; } <h1>用户 ...
- [转帖]支撑双11每秒17.5万单事务 阿里巴巴对JVM都做了些什么?
支撑双11每秒17.5万单事务 阿里巴巴对JVM都做了些什么? https://mp.weixin.qq.com/s?__biz=MzA3OTg5NjcyMg==&mid=2661671930 ...
- Redis 常用命令学四:有序集合类型命令
1.增加元素,修改存在元素的分数 127.0.0.1:6379> zadd score 99 a 88 b 66 c (integer) 3 127.0.0.1:6379> ZADD sc ...
- AlgorithmMap Dev Log
Log 2019.08.29 ------------------------------------------------------------------------------------- ...
- 谷歌大脑提出:基于NAS的目标检测模型NAS-FPN,超越Mask R-CNN
谷歌大脑提出:基于NAS的目标检测模型NAS-FPN,超越Mask R-CNN 朱晓霞发表于目标检测和深度学习订阅 235 广告关闭 11.11 智慧上云 云服务器企业新用户优先购,享双11同等价格 ...
- (三)Redis之数据结构概念以及数据结构之字符串
一.数据结构 五种数据类型: 字符串(String) 字符串列表(list) 有序字符串集合(sorted set) 哈希(hash) 字符串集合(set) 二.数据结构之字符串 二进制安全的,存入和 ...