[BZOJ]3674 可持久化并查集
来源:互联网 发布:php二维数组去掉重复值 编辑:程序博客网 时间:2024/04/28 20:46
3674: 可持久化并查集加强版
Time Limit: 15 Sec Memory Limit: 256 MB
Submit: 4051 Solved: 1503
[Submit][Status][Discuss]
Description
Description:
自从zkysb出了可持久化并查集后……
hzwer:乱写能AC,暴力踩标程
KuribohG:我不路径压缩就过了!
ndsf:暴力就可以轻松虐!
zky:……
n个集合 m个操作
操作:
1 a b 合并a,b所在集合
2 k 回到第k次操作之后的状态(查询算作操作)
3 a b 询问a,b是否属于同一集合,是则输出1否则输出0
请注意本题采用强制在线,所给的a,b,k均经过加密,加密方法为x = x xor lastans,lastans的初始值为0
0
题解
可持久化并查集… 其实我们发现每次合并如果按秩合并的话只会改变一个点的fa, 那么就好比主席树每次有一个点不同, 修改一条链. 那么我们就可以用主席树维护每个点的fa和每个点的rk(即按秩合并的rk). 按秩合并本身暴力爬树是log, 每次查fa也变成log, 那么就是log^2n的复杂度… 用主席树维护即可.
用路径压缩有两点不对:
1. 第i棵主席树的建立由于路径压缩会改变多个点的fa, 那么空间会增加很大一部分, 不像按秩合并只会改变一个点的fa.
2. 多次合并, 每次合并一个集合的root和一个单点, 触发find后等于无效. 这样多次操作就成了一条长链… 成一条长链后那么每次操作回到这个版本, 那么路径压缩就会很长.
#include<stdio.h>#include<algorithm>#define Boc register char#define Acce register intconst int maxn = 2e5 + 5;int n, m, ans;inline const int read(){ Acce x = 0; Boc ch = getchar(); while (ch < '0' || ch > '9') ch = getchar(); while (ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch = getchar(); return x;}struct node{ int fa, rk; node *ls, *rs;}pool[maxn * 50], *root[maxn], *tail = pool;node* build(int lf, int rg){ node* bt = ++ tail; if (lf == rg) { bt -> fa = lf, bt -> rk = 0; return bt; } int mid = (lf + rg) >> 1; bt -> ls = build(lf, mid); bt -> rs = build(mid + 1, rg); return bt;}void modify(node* &bt, node* pre, int lf, int rg, int pos, int val){ bt = ++ tail; if(lf == rg) { bt -> fa = val; return; } int mid = (lf + rg) >> 1; if(pos <= mid) bt -> rs = pre -> rs, modify(bt -> ls, pre -> ls, lf, mid, pos, val); else bt -> ls = pre -> ls, modify(bt -> rs, pre -> rs, mid + 1, rg, pos, val);}node* query(node* bt, int lf, int rg, int pos){ if(lf == rg) return bt; int mid = (lf + rg) >> 1; if(pos <= mid) return query(bt -> ls, lf, mid, pos); else return query(bt -> rs, mid + 1, rg, pos);}node* find(int u, int i){ node* p = query(root[i], 1, n, u); if(u == p -> fa) return p; return find(p -> fa, i);}int main(){ n = read(), m = read(); root[0] = build(1, n); node *p, *q; for (Acce i = 1; i <= m; ++ i) { int opt = read(), u, v; if (opt == 1) { u = read(), v = read(); root[i] = root[i - 1]; u ^= ans, v ^= ans; p = find(u, i - 1), q = find(v, i - 1); if (p -> fa == q -> fa) continue; if (p -> rk > q -> rk) std :: swap(p, q); modify(root[i], root[i - 1], 1, n, p -> fa, q -> fa); if(p -> rk == q -> rk) q -> rk ++; } if (opt == 2) u = read(), u ^= ans, root[i] = root[u]; if (opt == 3) { root[i] = root[i - 1]; u = read(), v = read(); u ^= ans, v ^= ans; p = find(u, i), q = find(v, i); ans = (p -> fa == q -> fa); printf("%d\n", ans); } }}
阅读全文
0 0
- BZOJ 3674 可持久化并查集加强版 可持久化并查集
- [BZOJ 3674]可持久化并查集加强版:可持久化并查集
- bzoj 3674 可持久化并查集加强版
- 【BZOJ】3674: 可持久化并查集加强版
- Bzoj 3674: 可持久化并查集加强版
- BZOJ 3673&3674 可持久化并查集
- BZOJ 3673 & 3674 可持久化并查集
- bzoj 3674 可持久化并查集加强版
- [BZOJ]3674 可持久化并查集
- bzoj 3674: 可持久化并查集加强版
- BZOJ 3674 可持久化并查集加强版 可持久化线段树
- bzoj 3673&&3674 可持久化并查集 可持久化线段树
- bzoj 3674: 可持久化并查集加强版 可持久化线段树
- BZOJ 3674: 可持久化并查集加强版/BZOJ 3673: 可持久化并查集 by zky 可持久化线段树
- BZOJ 3673 可持久化并查集 by zky && 3674 可持久化并查集加强版
- BZOJ 3673 可持久化并查集 by zky 可持久化并查集
- BZOJ 3673/3674(可持久化并查集 by zky,可持久化并查集加强版-可持久化数组)
- 【BZOJ】【P3673】【可持久化并查集】【题解】
- 共享单车三大迷局:人没了车没了钱没了!
- Shop项目--5. 显示商品详细信息,product_info.jsp
- 起底Uber旧金山AI实验室 一切为了生意!
- HYSBZ
- 揭密Oracle之七种武器之三:破译古老的谜题---共享CBC Latch的秘密
- [BZOJ]3674 可持久化并查集
- 第一章 java入门
- 阿里口碑无人餐厅明年落地 新能源汽车最高可贷85%
- JVM结构认知
- 专栏|小巧灵活的机器人异构系统平台:英特尔HERO
- 独家:87天,百度渡鸦智能音箱诞生记
- 谈谈 Python 程序的运行原理
- 纯干货-17 分布式深度学习原理、算法详细介绍
- SHELL中单引号