@(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. C\C++对于字符串输入处理

    1.scanf scanf以%s格式符读入字符串,会以空格为结束,也就是无法将空格读入.如果换成%c就可以读入,但是无法一次性读入一整行字符. 2.fgets 显然,fgets是一个读取带空格字符串的 ...

  2. linux-ngnix服务(一)

    httpd MPM: prefork:进程模型,两级结构,主进程master负责生成子进程,每个子进程负责响应一个请求 worker:线程模型,三级结构,主进程master负责生成子进程,每个子进程负 ...

  3. S3C6410串口平台设备注册流程分析

    1.mdesc->map_io() start_kernel -->setup_arch(&command_line); -->paging_init(mdesc); --& ...

  4. 合肥工业大学数据结构上机实验代码与实验报告(全)github地址

    我已经将这个学期的所有数据结构上机实验的代码与报告上传到github上了,一直都有这个想法,但没抽出时间来学习git.经过上周简单的练习后,我已经基本学会运营自己的代码仓库了.所有代码都是C++写的类 ...

  5. PAT Basic 1037

    1037 在霍格沃茨找零钱 如果你是哈利·波特迷,你会知道魔法世界有它自己的货币系统 —— 就如海格告诉哈利的:“十七个银西可(Sickle)兑一个加隆(Galleon),二十九个纳特(Knut)兑一 ...

  6. 关于EF使用脏读(连接会话开始执行设置隔离级别)

    SQL Server中事物隔离级别Read Uncommitted和with(nolock) 注意:应该使用后者(修改后的版本):

  7. codeforces Lightsabers (hard)

    题目大意: 给定每种球的数量,求从中选取k个球有多少种不同的取法,同种球视为相同的. 题解: 多项式(1+x+x^2+...+x^a[1])*(1+x+x^2+...+x^a[2])*(1+x+x^2 ...

  8. AVL树总结

    定义:一棵AVL树或者是空树,或者是具有下列性质的二叉搜索树:它的左子树和右子树都是AVL树,且左右子树的高度之差的绝对值不超过1 AVL树失衡旋转总结: 假如以T为根的子树失衡.定义平衡因子为 H( ...

  9. adb 命令大全

    传送门 --> https://github.com/mzlogin/awesome-adb ADB,即 Android Debug Bridge,它是 Android 开发/测试人员不可替代的 ...

  10. PYDay3-初识python

    Python 种类 c.j.iron.ruby等,主要有三类:cpython.xxxpython.pypy 种类繁多我们精通一种即可 编译流程: py代码->字节码->机器码->计算 ...