@(BZOJ)[可持久化并査集]

Description

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<n,m<=2*10^5

Sample Input

5 6
1 1 2
3 1 2
2 1
3 0 3
2 1
3 1 2

Sample Output

1
0
1

Solution

模板题.

BZOJ上的数据傻到不行.

还是去xsy上提交吧

#include <cstdio>
#include <cctype>
#include <cstring>
#include <algorithm> const int N = 1 << 18, M = 1 << 18;
int n; namespace Zeonfai
{
inline int getInt()
{
int a = 0, sgn = 1;
char c; while(! isdigit(c = getchar()))
sgn *= c == '-' ? -1 : 1; while(isdigit(c))
a = a * 10 + c - '0', c = getchar(); return a * sgn;
}
} struct persistentDisjointSet
{
int rt[M], tp; struct data
{
int pre, dep;
}; struct node
{
int suc[2];
data infr;
}nd[N * 18 + M * 18]; inline int newNode(int pre, int dep)
{
nd[tp].suc[0] = nd[tp].suc[1] = -1;
nd[tp].infr.pre = pre, nd[tp].infr.dep = dep;
return tp ++;
} int build(int L, int R)
{
int u = newNode(L == R ? L : -1, 1); if(L == R)
return u; int mid = L + R >> 1;
nd[u].suc[0] = build(L, mid), nd[u].suc[1] = build(mid + 1, R);
return u;
} inline void initialize()
{
memset(rt, -1, sizeof(rt));
tp = 0;
rt[0] = build(1, n);
} int find(int L, int R, int u, int a)
{
if(L == R)
return u; int mid = L + R >> 1; if(a <= mid)
return find(L, mid, nd[u].suc[0], a);
else
return find(mid + 1, R, nd[u].suc[1], a);
} inline int access(int tm, int a)
{
while(int u = find(1, n, rt[tm], a))
{
if(nd[u].infr.pre == a)
return a; a = nd[u].infr.pre;
}
} int newSegmentTree(int _u, int L, int R, int a, int b)
{
int u = tp ++;
nd[u] = nd[_u]; if(L == R)
return u; int mid = L + R >> 1; if((a >= L && a <= mid) || (b >= L && b <= mid))
nd[u].suc[0] = newSegmentTree(nd[_u].suc[0], L, mid, a, b); if((a > mid && a <= R) || (b > mid && b <= R))
nd[u].suc[1] = newSegmentTree(nd[_u].suc[1], mid + 1, R, a, b); return u;
} inline void merge(int tm, int a, int b)
{
int rtA = access(tm - 1, a), rtB = access(tm - 1, b); if(rtA == rtB)
{
rt[tm] = rt[tm - 1];
return;
} rt[tm] = newSegmentTree(rt[tm - 1], 1, n, rtA, rtB);
int u = find(1, n, rt[tm], rtA), v = find(1, n, rt[tm], rtB); if(nd[u].infr.dep == nd[v].infr.dep)
{
++ nd[u].infr.dep;
nd[v].infr.pre = rtA;
return;
} if(nd[u].infr.dep > nd[v].infr.dep)
nd[v].infr.pre = rtA;
else
nd[u].infr.pre = rtB;
} inline void accessHistory(int tm, int _tm)
{
rt[tm] = rt[_tm];
} inline int query(int tm, int a, int b)
{
rt[tm] = rt[tm - 1];
int preA = access(tm, a), preB = access(tm, b); if(preA == preB)
return 1;
else
return 0;
}
}st; int main()
{
#ifndef ONLINE_JUDGE
freopen("BZOJ3674.in", "r", stdin);
freopen("BZOJ3674.out", "w", stdout);
#endif using namespace Zeonfai; n = getInt();
int m = getInt(), lstAns = 0, tm = 0;
st.initialize(); while(m --)
{
int opt = getInt(); if(opt == 1)
{
int a = getInt() ^ lstAns, b = getInt() ^lstAns;
st.merge(++ tm, a, b);
}
else if(opt == 2)
{
int a = getInt() ^ lstAns;
st.accessHistory(++ tm, a);
}
else if(opt == 3)
{
int a = getInt() ^ lstAns, b = getInt() ^ lstAns;
printf("%d\n", lstAns = st.query(++ tm, a, b));
}
}
}

BZOJ3674 可持久化并査集的更多相关文章

  1. bzoj3673可持久化并查集 by zky&&bzoj3674可持久化并查集加强版

    bzoj3673可持久化并查集 by zky 题意: 维护可以恢复到第k次操作后的并查集. 题解: 用可持久化线段树维护并查集的fa数组和秩(在并查集里的深度),不能路径压缩所以用按秩启发式合并,可以 ...

  2. bzoj3674 可持久化并查集

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

  3. BZOJ3674: 可持久化并查集加强版

    题目:http://www.lydsy.com/JudgeOnline/problem.php?id=3674 题解:主要是可持久化的思想.膜拜了一下hzwer的代码后懂了. 其实本质是可持久化fa数 ...

  4. 2019.01.21 bzoj3674: 可持久化并查集加强版(主席树+并查集)

    传送门 题意:维护可持久化并查集,支持在某个版本连边,回到某个版本,在某个版本 询问连通性. 思路: 我们用主席树维护并查集fafafa数组,由于要查询历史版本,因此不能够用路径压缩. 可以考虑另外一 ...

  5. bzoj3673 bzoj3674可持久化并查集

    并查集都写不来了qwq 之前写的是错的 sz的初值都是0,这样怎么加就都是0了,水这道题还是可以,但是加强版就过不了了 #include<cstdio> #include<cstri ...

  6. BZOJ3674 可持久化并查集加强版 可持久化 并查集

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ3674 题意概括 n个集合 m个操作操作:1 a b 合并a,b所在集合2 k 回到第k次操作之后的 ...

  7. [BZOJ3674]可持久化并查集加强版&[BZOJ3673]可持久化并查集 by zky

    思路: 用主席树维护并查集森林,每次连接时新增结点. 似乎并不需要启发式合并,我随随便便写了一个就跑到了3674第一页?3673是这题的弱化版,本来写个暴力就能过,现在借用加强版的代码(去掉异或),直 ...

  8. 【可持久化数组】【rope】bzoj3673 bzoj3674 可持久化并查集 by zky

    rope教程:http://blog.csdn.net/iamzky/article/details/38348653 Code(bzoj3673): #include<cstdio> # ...

  9. BZOJ3674可持久化并查集(模板)

    没什么可说的,就是一个可持久化线段树维护一个数组fa以及deep按秩合并好了 注意一下强制在线 蒟蒻的我搞了好长时间QAQ 贴代码: #include<cstdio> #include&l ...

随机推荐

  1. java常用流处理工具StreamTool 常见的InputStream流转字符串, 转字节数组等等

    ava 常用流处理工具 StreamTool ,常见的InputStream 流转字符串, 转字节数组等等 **应用场景: ** 1. 文件上传 2. js / css / img 等文件读取输出. ...

  2. Mac 录制视频,并转为GIF格式

    内容中包含 base64string 图片造成字符过多,拒绝显示

  3. ubuntu命令行卸载并清理软件

    卸载软件,可以使用下面这两种方式之一: sudo apt-get remove --purge [software name] sudo apt-get autoremove --purge [sof ...

  4. Linux进程通信之共享内存实现生产者/消费者模式

    共享内存 共享内存是内核为进程创建的一个特殊内存段,它将出现在进程自己的地址空间中,其它进程可以将同一段共享内存连接(attach)到自己的地址空间.这是最快的进程间通信方式,但是不提供任何同步功能( ...

  5. GIMP如何创建layer masks,创建,删除,禁用,复制mask

    这次案例是背景替换,采用创建一个新的layer masks: 前期准备好要处理的图片:     1.创建一个新的图层,选择Layer,点击Mask,选择Add Layer Mask: 根据情况选择合适 ...

  6. FastJson生成json时,显示Null属性

    FastJson生成json时,默认不会输出null字段. 移动端,有时候,需要后端提供完整的字段说明. Map < String , Object > jsonMap = new Has ...

  7. Flash生成HTML5动画方法

      方法一:利用“swiffy”将Flash转换成HTML5动画. 首先,我们需要下载一款基于“Flash”程序的插件,名称为“swiffy”,这是一款由谷歌推出的一个Flash扩展,可以通过“Fla ...

  8. OpennSSL之基本了解

    HTTPS是一种协议,等于HTTP+TLS(由于历史原因,SSL3.0之后就被TLS1.0替代了).openssl是一套开源工具集,主要有两个特性: 实现了ssl2,ssl3,TLSv1,TLSv1. ...

  9. WordPress添加前台注册功能

    一.添加注册表单 1.首先在当前主题的目录下新建一个php文件,命名为reg-page.php,然后将page.php中的所有代码复制到reg-page.php中: 2.删除reg-page.php开 ...

  10. 【SQL Server】SQL常用系统函数

    SQL常用系统函数 函数类型 函数表达式 功能 应用举例 字符串函数 SubString(表达式,起始,长度) 取子串 SubString('ABCDEFG',3,4) Right(表达式,长度) 右 ...