P3402

通过主席树维护不同版本的并查集,注意要采用按秩合并的方式,路径压缩可能会爆。

 1 #include <bits/stdc++.h>
2 using namespace std;
3 const int N = 3e5 + 10;
4 int n, m, rt[N * 30];
5 struct node {
6 int ls, rs, dep, fa;//fa的值都是在1~n范围中的
7 }t[N * 30];
8 namespace SegmentTree {
9 #define mid ((l + r) >> 1)
10 #define lson t[i].ls, l, mid
11 #define rson t[i].rs, mid + 1, r
12 int cnt;
13 void build(int &i, int l, int r) {
14 i = ++ cnt;
15 if (l == r) {t[i].fa = l; return ;}//初始时节点父亲就是自己
16 build(lson), build(rson);
17 }
18 void merge(int j, int &i, int l, int r, int pos1, int pos2) {
19 //pos1是深度较小的节点的fa,找到pos1的位置,将该位置的fa改为pos2,也就是合并操作
20 i = ++ cnt;
21 t[i] = t[j];//复制
22 if (l == r) {
23 t[i].fa = pos2;
24 return ;
25 }
26 if (pos1 <= mid) merge(t[j].ls, lson, pos1, pos2);
27 else merge(t[j].rs, rson, pos1, pos2);
28 }
29 void update(int i, int l, int r, int pos) {
30 if (l == r) {t[i].dep ++; return ;}
31 if (pos <= mid) update(lson, pos);
32 else update(rson, pos);
33 }
34 int query(int i, int l, int r, int pos) {//返回节点pos的编号
35 if (l == r) return i;
36 if (pos <= mid) return query(lson, pos);
37 else return query(rson, pos);
38 }
39 int find(int i, int pos) {//类似并查集找祖先操作
40 int now = query(i, 1, n, pos);
41 if (t[now].fa == pos) return now;//也是返回节点编号
42 return find(i, t[now].fa);
43 }
44 #undef mid
45 #undef lson
46 #undef rson
47 }
48 using namespace SegmentTree;
49 int main() {
50 scanf("%d %d", &n, &m);
51 build(rt[0], 1, n);
52 for (int i = 1; i <= m; i ++) {
53 int opt, x, y;
54 scanf("%d %d", &opt, &x);
55 if(opt == 1) {//合并x, y所在集合
56 scanf("%d", &y);
57 int posx, posy;
58 rt[i] = rt[i - 1];//复制新版本
59 posx = find(rt[i], x), posy = find(rt[i], y);
60 if (t[posx].fa != t[posy].fa) {//按秩合并
61 if (t[posx].dep > t[posy].dep) swap(posx, posy);
62 merge(rt[i - 1], rt[i], 1, n, t[posx].fa, t[posy].fa);
63 if (t[posx].dep == t[posy].dep) update(rt[i], 1, n, t[posy].fa);
64 //避免深度相同
65 }
66 }
67 else if(opt == 2) rt[i] = rt[x];
68 else if(opt == 3) {
69 scanf("%d", &y);
70 rt[i] = rt[i - 1];
71 int posx, posy;
72 posx = find(rt[i], x), posy = find(rt[i], y);
73 if (t[posx].fa == t[posy].fa) puts("1");
74 else puts("0");
75 }
76 }
77 return 0;
78 }

最新文章

  1. 2.OC蓝牙功能
  2. android服务之启动方式
  3. CodeForces - 699B One Bomb
  4. LOB字段存放在指定表空间 清理CLOB字段及压缩CLOB空间
  5. 一个模拟&quot;显示桌面.scf&quot;程序的JS小函数
  6. 20141009---Visual Studio 2012 预定义数据类型
  7. magento install
  8. linux服务器监控流量sh脚本
  9. BZOJ 1029: [JSOI2007]建筑抢修
  10. ceph源码之一
  11. VC 绘图技巧--自定义形状图形
  12. 用EnableMenuItem不能使菜单变灰的原因
  13. oracle_powerdesinger逆向工程 , PDM 文件 注释到name的完美解决方案 comment2name
  14. linux中如何用root去修改其他用户的密码
  15. bootstrap学习笔记之基础导航条 http://www.imooc.com/code/3111
  16. 《java.util.concurrent 包源码阅读》07 LinkedBlockingQueue
  17. SpringMVC RequestMapping注解
  18. KVO and Swift
  19. httpclient的封装完整版
  20. Elasticsearch-6.7.0系列(三)5601端口 kibana——ES的UI界面

热门文章

  1. 【人工智能】【Python】Matplotlib基础
  2. python对象的独有功能与面向对象的特征
  3. 把酒言欢话聊天,基于Vue3.0+Tornado6.1+Redis发布订阅(pubsub)模式打造异步非阻塞(aioredis)实时(websocket)通信聊天系统
  4. Latex查表
  5. C 语言 时间函数使用技巧(汇总)
  6. iNeuOS工业互联网操作系统,在航天和军工测控领域的应用
  7. Luogu2455 [SDOI2006]线性方程组 (高斯消元)
  8. 【unity游戏入门】1 环境安装
  9. Mac系统下Datagrip打不开、点击没反应?
  10. VSCODE 配置远程调试环境