可持久化并查集我觉得就是可持久化数组的一种应用。可持久化数组,顾名思义,就是有历史版本的数组,那么如果我们暴力修改储存的话,修改O(n)查询O(1),空间O(n*m),这样肯定不可行,那么我们发现主席树有这样的功能,他可以快速复制,修改O(log),查询O(log),空间(m*log),是一个可行的方案。然后我们可持久化f数组维护fa,每次按照深度启发式合并,不进行路径压缩,这样能保证时间复杂度位单次O(log^2),空间复杂度为O(2*n+m*log)。我不知道为什么不路径压缩,路径压缩是完全可以的,但是他的时间复杂度和空间复杂度似乎都不如不路径压缩看,而且似乎并不好打。

#include <cstdio>
using namespace std;
inline void read(int &sum){
register char ch=getchar();
for(sum=;ch<''||ch>'';ch=getchar());
for(;ch>=''&&ch<='';sum=(sum<<)+(sum<<)+ch-'',ch=getchar());
}
const int N=;
struct Segment_Tree{
Segment_Tree *ch[];int f,deep;
void* operator new(size_t);
}*root[N],*null,*C,*mempool;
int n,m;
void* Segment_Tree :: operator new(size_t){
if(C==mempool)C=new Segment_Tree[(<<)+],mempool=C+(<<)+;
return C++;
}
inline void build(Segment_Tree *&p,int l,int r){
p=new Segment_Tree,p->deep=p->f=;
if(l==r){
p->f=l,p->deep=,p->ch[]=p->ch[]=null;
return;
}
build(p->ch[],l,(l+r)>>);
build(p->ch[],((l+r)>>)+,r);
}
inline void insert(Segment_Tree *&p,Segment_Tree *last,int pos,int key,int l,int r){
p=new Segment_Tree,*p=*last;
if(l==r){
p->f=key;return;
}
if(pos<=((l+r)>>))insert(p->ch[],last->ch[],pos,key,l,((l+r)>>));
else insert(p->ch[],last->ch[],pos,key,((l+r)>>)+,r);
}
inline void update(Segment_Tree *p,int pos){
register int l=,r=n;
while(l!=r){
if(pos<=((l+r)>>)){
p=p->ch[],r=((l+r)>>);
}else{
p=p->ch[],l=((l+r)>>)+;
}
}
p->deep++;
}
inline int deep(Segment_Tree *p,int pos){
register int l=,r=n;
while(l!=r){
if(pos<=((l+r)>>)){
p=p->ch[],r=((l+r)>>);
}else{
p=p->ch[],l=((l+r)>>)+;
}
}
return p->deep;
}
inline int F(Segment_Tree *p,int pos){
register int l=,r=n;
while(l!=r){
if(pos<=((l+r)>>)){
p=p->ch[],r=((l+r)>>);
}else{
p=p->ch[],l=((l+r)>>)+;
}
}
return p->f;
}
inline int find_root(Segment_Tree *p,int x){
int fa=F(p,x);
return fa==x?x:find_root(p,fa);
}
inline void Init(){
null=new Segment_Tree,null->ch[]=null->ch[]=null,null->f=,null->deep=;
read(n),read(m);
build(root[],,n);
}
inline void Work(){
register int ans=,opt,a,b,x,y,d1,d2;
for(register int i=;i<=m;i++){
read(opt);
switch(opt){
case :read(a),a^=ans,read(b),b^=ans;
x=find_root(root[i-],a),y=find_root(root[i-],b);
if(x==y){
root[i]=root[i-];
break;
}
d1=deep(root[i-],x),d2=deep(root[i-],y);
if(d1>d2)x^=y^=x^=y;insert(root[i],root[i-],x,y,,n);
if(d1==d2)update(root[i],y);
break;
case :read(a),a^=ans;
root[i]=root[a];break;
case :read(a),read(b),a^=ans,b^=ans;
root[i]=root[i-];
x=find_root(root[i],a),y=find_root(root[i],b);
if(x==y)puts(""),ans=;
else puts(""),ans=;
break;
}
}
}
int main(){
Init();
Work();
return ;
}

【BZOJ3674】可持久化并查集加强版的更多相关文章

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

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

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

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

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

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

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

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

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

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

  6. 【BZOJ3673/3674】可持久化并查集/可持久化并查集加强版 可持久化线段树

    [BZOJ3674]可持久化并查集加强版 Description Description:自从zkysb出了可持久化并查集后……hzwer:乱写能AC,暴力踩标程KuribohG:我不路径压缩就过了! ...

  7. BZOJ 3674 可持久化并查集加强版(路径压缩版本)

    /* bzoj 3674: 可持久化并查集加强版 http://www.lydsy.com/JudgeOnline/problem.php?id=3674 用可持久化线段树维护可持久化数组从而实现可持 ...

  8. BZOJ 3674 可持久化并查集加强版(按秩合并版本)

    /* bzoj 3674: 可持久化并查集加强版 http://www.lydsy.com/JudgeOnline/problem.php?id=3674 用可持久化线段树维护可持久化数组从而实现可持 ...

  9. bzoj3674 可持久化并查集

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

随机推荐

  1. Could not obtain transaction-synchronized Session for current thread 错误的解决方法!

    BsTable bsTable = new BsTable(); // String time = request.getParameter("date"); String tim ...

  2. R语言学习笔记(十一):零碎知识点(26-30)

    26--aggregate( ) 函数aggregate()对分组中的每一个变量调用tapply()函数. aggregate(a,list,f) 第二个参数必须是列表.也就是因子部分. 第三个参数即 ...

  3. Xshell入门教程介绍

    免费软件 Xshell和 Xftp 都是 NetSarang 出品的优秀网络管理.安全传输工具.Xshell 是一个免费的安全终端仿真器,可以作为 SSH.TELNET 或 RLOGIN 的终端模拟, ...

  4. 基于Ubuntu Server 16.04 LTS版本安装和部署Django之(三):设置上传文件夹权限(这里测试用完全共享)

    基于Ubuntu Server 16.04 LTS版本安装和部署Django之(一):安装Python3-pip和Django 基于Ubuntu Server 16.04 LTS版本安装和部署Djan ...

  5. 【多线程】 Task

    [多线程] Task 一. 常用方法: 1. ContinueWith : 当前 Task 完成后, 执行传入的 Task 2. Delay : 创建一个等待的 Task,只有在调用 Wait 方法时 ...

  6. loadrunner创建测试脚本运行无响应 不记录脚本

    解决一运行User Generator直接程序卡死无响应的办法. (1)“我的电脑”点右键->属性->高级 点选“性能”中的“设置” (2)打开对话框后,进入“数据执行保护”,如果空白框中 ...

  7. VS2010使用NuGet程序包管理器

    使用C#过程中经常需要使用一些扩展包,例如sqlite,json解析等. VS2010自带了一个扩展管理器,里面可以下载到AStyle,Visual Assit等有用的插件. VS2010中点击[工具 ...

  8. 「日常训练」「小专题·图论」 Frogger (1-1)

    题意 分析 变形的dijkstra. 分析题意之后补充. 代码 // Origin: // Theme: Graph Theory (Basic) // Date: 080518 // Author: ...

  9. 「题目代码」P1034~P1038(Java)

    P1034 C基础-求同存异 import java.util.*; import java.io.*; import java.math.BigInteger; public class Main ...

  10. 怎样安装Python3

    在浏览器地址栏输入https://www.python.org/ 打开Python官网 好了,安装完成了! 可以把安装路径C:\Users\Administrator\AppData\Local\Pr ...