zz:https://www.cnblogs.com/cjoierljl/p/9567859.html

https://www.cnblogs.com/peng-ym/p/9357220.html

n个集合 m个操作
操作:
1 a b 合并a,b所在集合
2 k 回到第k次操作之后的状态(查询算作操作)
3 a b 询问a,b是否属于同一集合,是则输出1否则输出0

0<n,m<=2*10^4

Sample Input

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

Sample Output

1
0
1

#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<iomanip>
#include<algorithm>
#include<ctime>
#include<queue>
#include<stack>
#include<vector>
#define lst long long
#define ldb long double
#define N 200050
#define lson ljl[now].ls
#define rson ljl[now].rs
using namespace std;
const int Inf=1e9;
int read()
{
int s=0,m=0;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')m=1;ch=getchar();}
while(ch>='0'&&ch<='9')s=(s<<3)+(s<<1)+(ch^48),ch=getchar();
return m?-s:s;
} int n,Q,tot;
int dep[N*30],fa[N*30];
int Edi[N];//版本编号
struct TREE{int ls,rs;}ljl[N*30];
//主席树部分
void Build(int &now,int le,int ri)
{
if(!now)now=++tot;
if(le==ri)
{
fa[now]=le;//第now个结点属于第le个集合
return;
}//并查集初始化
int mid=(le+ri)>>1;
Build(lson,le,mid);
Build(rson,mid+1,ri);
} void Update(int &now,int pre,int le,int ri,int loc,int ff)
//now代表新开线段树,pre是上一个线段树对应结点的编号
//loc及ff,是指将loc并到ff这个集合中
{
now=++tot;//新开log个节点
if(le==ri)
{
dep[now]=dep[pre];//copy过来
fa[now]=ff;//第now个结点属于ff集合
return;
}
lson=ljl[pre].ls,rson=ljl[pre].rs;//把前面的树“复制”过来
int mid=(le+ri)>>1;
if(loc<=mid)
Update(lson,ljl[pre].ls,le,mid,loc,ff);
else
Update(rson,ljl[pre].rs,mid+1,ri,loc,ff);
} int Query(int now,int le,int ri,int loc)
{//查到loc这个集合,在目前这个线段中的结点编号
if(le==ri)
return now;
int mid=(le+ri)>>1;
if(loc<=mid)
return Query(lson,le,mid,loc);
else
return Query(rson,mid+1,ri,loc);
}
void add(int now,int le,int ri,int loc)
{//按秩合并的树高改变
if(le==ri)
{
dep[now]++;
return;
}
int mid=(le+ri)>>1;
if(loc<=mid)
add(lson,le,mid,loc);
else
add(rson,mid+1,ri,loc);
} int Find_fa(int edi,int now)
{
int ff=Query(edi,1,n,now);
//查询在这一版本里now这个集合所在的结点编号
if(now==fa[ff])
//如果这个结点编号属于now这个集合,则找到
//如果不一样,则取出这个结点编号所指向的集合
return ff;
return Find_fa(edi,fa[ff]);//接着去找
} int main()
{
n=read(),Q=read();
Build(Edi[0],1,n);
for(int i=1;i<=Q;++i)
{
int opt=read();
if(opt==1)
{
Edi[i]=Edi[i-1];//先copy过来
int x=read(),y=read();
int fx=Find_fa(Edi[i],x);//取出结点编号
int fy=Find_fa(Edi[i],y);//同上
if(fa[fx]==fa[fy]) //如果是同一个集合
continue;
if(dep[fx]>dep[fy])
swap(fx,fy);//按秩合并,把x往y合并(dep小的往大的合并)
Update(Edi[i],Edi[i-1],1,n,fa[fx],fa[fy]);
//因为有合并操作,所以要新开线段树出来了
//注意后面两个参数是集合编号
if(dep[fx]+1>dep[fy])
add(Edi[i],1,n,fa[fy]);
}
if(opt==2)
{
int kk=read();
Edi[i]=Edi[kk];
}
if(opt==3)
{
Edi[i]=Edi[i-1];
int x=read(),y=read();
int fx=Find_fa(Edi[i],x),fy=Find_fa(Edi[i],y);
if(fa[fx]==fa[fy])
puts("1");
else
puts("0");
}
}
return 0;
}

  

可持久化并查集 by zky的更多相关文章

  1. 【BZOJ3673】&&【BZOJ3674】: 可持久化并查集 by zky 可持久化线段树

    没什么好说的. 可持久化线段树,叶子节点存放父亲信息,注意可以规定编号小的为父亲. Q:不是很清楚空间开多大,每次询问父亲操作后修改的节点个数是不确定的.. #include<bits/stdc ...

  2. BZOJ3673 可持久化并查集 by zky 【主席树】

    BZOJ3673 可持久化并查集 by zky Description n个集合 m个操作 操作: 1 a b 合并a,b所在集合 2 k 回到第k次操作之后的状态(查询算作操作) 3 a b 询问a ...

  3. 3673: 可持久化并查集 by zky

    3673: 可持久化并查集 by zky Time Limit: 5 Sec  Memory Limit: 128 MBSubmit: 2170  Solved: 978[Submit][Status ...

  4. Bzoj 3673: 可持久化并查集 by zky(主席树+启发式合并)

    3673: 可持久化并查集 by zky Time Limit: 5 Sec Memory Limit: 128 MB Description n个集合 m个操作 操作: 1 a b 合并a,b所在集 ...

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

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

  6. 【BZOJ】3673: 可持久化并查集 by zky & 3674: 可持久化并查集加强版(可持久化线段树)

    http://www.lydsy.com/JudgeOnline/problem.php?id=3674 http://www.lydsy.com/JudgeOnline/problem.php?id ...

  7. [bzoj3673][可持久化并查集 by zky] (rope(可持久化数组)+并查集=可持久化并查集)

    Description n个集合 m个操作 操作: 1 a b 合并a,b所在集合 2 k 回到第k次操作之后的状态(查询算作操作) 3 a b 询问a,b是否属于同一集合,是则输出1否则输出0 0& ...

  8. BZOJ 3673 可持久化并查集 by zky && BZOJ 3674 可持久化并查集加强版 可持久化线段树

    既然有了可持久化数组,就有可持久化并查集.. 由于上课讲过说是只能按秩合并(但是我也不确定...),所以就先写了按秩合并,相当于是维护fa[]和rk[] getf就是在这棵树中找,直到找到一个点的fa ...

  9. 【BZOJ 3674】可持久化并查集加强版&【BZOJ 3673】可持久化并查集 by zky 用可持久化线段树破之

    最后还是去掉异或顺手A了3673,,, 并查集其实就是fa数组,我们只需要维护这个fa数组,用可持久化线段树就行啦 1:判断是否属于同一集合,我加了路径压缩. 2:直接把跟的值指向root[k]的值破 ...

  10. 【BZOJ3673】【可持久化并查集】可持久化并查集 by zky

    Description n个集合 m个操作操作:1 a b 合并a,b所在集合2 k 回到第k次操作之后的状态(查询算作操作)3 a b 询问a,b是否属于同一集合,是则输出1否则输出0 0<n ...

随机推荐

  1. vue打包后element-ui部分样式(图标)异常问题

    vue项目使用element-ui组件,打包后部分样式(上下左右箭头)异常,变成方框了. 页面报warn错误,有个字体找不到. 解决办法:在build文件夹下找到utils.js,加上一行public ...

  2. 十二、S3C2440 裸机 — SDRAM

    12.1 SDRAM 介绍 12.1.1 SDRAM 定义 SDRAM(Synchronous Dynamic Random Access Memory):同步动态随机存储器-内存条 同步是指内存工作 ...

  3. 在同一个方法里,有redis,数据库和api,如何保证方法的事务性或者最终一致性?

    https://segmentfault.com/q/1010000017519179/a-1020000017547192

  4. squid之------安装与基本配置

    1.rpm安装squid yum -y install squid 2.squid主要组成部分 服务名:squid 主程序:/usr/sbin/squid 配置目录:/etc/squid 主配置文件: ...

  5. 移动端 使用 vConsole调试

    前言 用vue 写移动端代码,有个报名页面 就在iOS 9下出现问题,vue的循环渲染都正常,一开始的数据也能取到.证明不是vue的兼容性问题 但是在用户点击按钮发现不能点击进入跳转 工具 推荐使用  ...

  6. 【NOIP2014模拟8.25】设备塔

    题目 为了封印辉之环,古代塞姆利亚大陆的人民在异空间中建造了一座设备塔. 简单的说,这座设备塔是一个漂浮在异空间中的圆柱体,圆柱体两头的圆是计算核心,而侧面则是 传输信息所用的数据通道,划分成N *m ...

  7. 【leetcode&CN&竞赛】1198.Find Smallest Common Element in All Rows

    题目如下: 给你一个矩阵 mat,其中每一行的元素都已经按 递增 顺序排好了.请你帮忙找出在所有这些行中 最小的公共元素. 如果矩阵中没有这样的公共元素,就请返回 -1. 示例: 输入:mat = [ ...

  8. latex beamer技巧

    %章节标题\section{Related work(LSH)} %开始一页ppt \begin{frame}{Related work}{} \partitle{Locality-Sensitive ...

  9. BZOJ 3143 Luogu P3232 [HNOI2013]游走 (DP、高斯消元)

    题目链接: (bzoj) https://www.lydsy.com/JudgeOnline/problem.php?id=3143 (luogu) https://www.luogu.org/pro ...

  10. sqli-lab(14)

    POST型的 双注入 0X01随便测试一下 在password输入"会报错  "#就不报错了 那么应该是“”的闭合 但是没有回显的值 只有报错的信息 那我们是不是该考虑从报错的语句 ...