bzoj3673可持久化并查集 by zky

题意:

维护可以恢复到第k次操作后的并查集。

题解:

用可持久化线段树维护并查集的fa数组和秩(在并查集里的深度),不能路径压缩所以用按秩启发式合并,可以使合并均摊复杂度为O(nlog2n)。可持久化线段树实际上就是在更新节点时按主席树的插入方式新建一条路径(其实主席树就是可持久化权值线段树)。

代码:

 #include <cstdio>
#include <cstring>
#include <algorithm>
#define maxn 30000
#define inc(i,j,k) for(int i=j;i<=k;i++)
using namespace std; int fa[maxn*],ch[maxn*][],dep[maxn*],pos[maxn*],sz,n,m,rt[maxn];
inline int read(){
char ch=getchar(); int f=,x=;
while(ch<''||ch>''){if(ch=='-')f=-; ch=getchar();} while(ch>=''&&ch<='')x=x*+ch-'',ch=getchar();
return f*x;
}
void build(int &x,int l,int r){
x=++sz; if(l==r){fa[x]=l; dep[x]=; pos[x]=l; return;}
int mid=(l+r)>>; build(ch[x][],l,mid); build(ch[x][],mid+,r);
}
void updatefa(int &x,int l,int r,int a,int b){
sz++; fa[sz]=fa[x]; dep[sz]=dep[x]; pos[sz]=pos[x]; ch[sz][]=ch[x][]; ch[sz][]=ch[x][];
x=sz; if(l==r){fa[x]=b; return;}
int mid=(l+r)>>; if(a<=mid)updatefa(ch[x][],l,mid,a,b);else updatefa(ch[x][],mid+,r,a,b);
}
void updatedep(int &x,int l,int r,int a,int b){
sz++; fa[sz]=fa[x]; dep[sz]=dep[x]; pos[sz]=pos[x]; ch[sz][]=ch[x][]; ch[sz][]=ch[x][];
x=sz; if(l==r){dep[x]=b; return;}
int mid=(l+r)>>; if(a<=mid)updatedep(ch[x][],l,mid,a,b);else updatedep(ch[x][],mid+,r,a,b);
}
int query(int x,int l,int r,int a){
if(l==r)return x; int mid=(l+r)>>;
if(a<=mid)return query(ch[x][],l,mid,a);else return query(ch[x][],mid+,r,a);
}
int find(int x,int y){
int z=query(x,,n,y); if(fa[z]==pos[z])return z;else return find(x,fa[z]);
}
void merge(int &s,int x,int y){
int z1=find(s,x),z2=find(s,y); if(pos[z1]==pos[z2])return; if(dep[z1]>dep[z2])swap(z1,z2);
int abc=max(dep[z2],dep[z1]+); updatefa(s,,n,pos[z1],pos[z2]); updatedep(s,,n,pos[z2],abc);
}
int main(){
n=read(); m=read(); build(rt[],,n);
inc(i,,m){
int opt=read();
if(opt==){int a=read(),b=read(); rt[i]=rt[i-]; merge(rt[i],a,b);}
if(opt==){int k=read(); rt[i]=rt[k];}
if(opt==){
int a=read(),b=read(); rt[i]=rt[i-];
if(pos[find(rt[i],a)]==pos[find(rt[i],b)])puts("");else puts("");
}
}
return ;
}

------------------------------------------------------------------------------------------------------------------------------------------

bzoj3674可持久化并查集加强版

题意:

同3673,但强制在线且点数操作数≤200000

题解:

T个不停,后来看黄学长博客把数组n*2(log2n)开成结果A了,后来突然明白我fa数组和dep数组是分开维护的,也就是说每次操作新建了两条路径,当然要*2,QAQ~

代码:

 #include <cstdio>
#include <cstring>
#include <algorithm>
#define maxn 200010
#define inc(i,j,k) for(int i=j;i<=k;i++)
using namespace std; int fa[maxn*],ch[maxn*][],dep[maxn*],pos[maxn*],sz,n,m,rt[maxn];
inline int read(){
char ch=getchar(); int f=,x=;
while(ch<''||ch>''){if(ch=='-')f=-; ch=getchar();} while(ch>=''&&ch<='')x=x*+ch-'',ch=getchar();
return f*x;
}
void build(int &x,int l,int r){
x=++sz; if(l==r){fa[x]=l; dep[x]=; pos[x]=l; return;}
int mid=(l+r)>>; build(ch[x][],l,mid); build(ch[x][],mid+,r);
}
void updatefa(int &x,int l,int r,int a,int b){
sz++; fa[sz]=fa[x]; dep[sz]=dep[x]; pos[sz]=pos[x]; ch[sz][]=ch[x][]; ch[sz][]=ch[x][];
x=sz; if(l==r){fa[x]=b; return;}
int mid=(l+r)>>; if(a<=mid)updatefa(ch[x][],l,mid,a,b);else updatefa(ch[x][],mid+,r,a,b);
}
void updatedep(int &x,int l,int r,int a,int b){
sz++; fa[sz]=fa[x]; dep[sz]=dep[x]; pos[sz]=pos[x]; ch[sz][]=ch[x][]; ch[sz][]=ch[x][];
x=sz; if(l==r){dep[x]=b; return;}
int mid=(l+r)>>; if(a<=mid)updatedep(ch[x][],l,mid,a,b);else updatedep(ch[x][],mid+,r,a,b);
}
int query(int x,int l,int r,int a){
if(l==r)return x; int mid=(l+r)>>;
if(a<=mid)return query(ch[x][],l,mid,a);else return query(ch[x][],mid+,r,a);
}
int find(int x,int y){
int z=query(x,,n,y); if(fa[z]==pos[z])return z;else return find(x,fa[z]);
}
void merge(int &s,int x,int y){
int z1=find(s,x),z2=find(s,y); if(pos[z1]==pos[z2])return; if(dep[z1]>dep[z2])swap(z1,z2);
int abc=max(dep[z2],dep[z1]+); updatefa(s,,n,pos[z1],pos[z2]); updatedep(s,,n,pos[z2],abc);
}
int main(){
n=read(); m=read(); build(rt[],,n); int last=;
inc(i,,m){
int opt=read();
if(opt==){int a=read()^last,b=read()^last; rt[i]=rt[i-]; merge(rt[i],a,b);}
if(opt==){int k=read()^last; rt[i]=rt[k];}
if(opt==){
int a=read()^last,b=read()^last; rt[i]=rt[i-];
if(pos[find(rt[i],a)]==pos[find(rt[i],b)])puts(""),last=;else puts(""),last=;
}
}
return ;
}

20160623

bzoj3673可持久化并查集 by zky&&bzoj3674可持久化并查集加强版的更多相关文章

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

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

  2. bzoj3673: 可持久化并查集 by zky&&3674: 可持久化并查集加强版

    主席树可持久化数组,还挺好YY的 然而加强版要路径压缩.. 发现压了都RE 结果看了看数据,默默的把让fx的父亲变成fy反过来让fy的父亲变成fx 搞笑啊 #include<cstdio> ...

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

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

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

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

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

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

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

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

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

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

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

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

  9. bzoj 3673&3674: 可持久化并查集 by zky

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

随机推荐

  1. 容器技术之Docker资源限制

    上一篇我们聊到了docker容器的单机编排工具docker-compose的简单使用,回顾请参考https://www.cnblogs.com/qiuhom-1874/p/13121678.html: ...

  2. 使用python解线性矩阵方程(numpy中的matrix类)

    这学期有一门运筹学,讲的两大块儿:线性优化和非线性优化问题.在非线性优化问题这里涉及到拉格朗日乘子法,经常要算一些非常变态的线性方程,于是我就想用python求解线性方程.查阅资料的过程中找到了一个极 ...

  3. rest_framework django 简单使用(数据库创建数据, 覆盖数据, 其他的大同小异)

    事先说几个坑:数据库定义字段时候,不要定义name 要定义 username 首先, 定义model(简单定义) from django.db import models from django.co ...

  4. VMware历史版本下载【1.0~3.0】

    前提:此为走HTTP协议的FTP伺服器,而且有直到Vmware3.0[之后就没了]的版本 link:http://linux.mathematik.tu-darmstadt.de/pub/linux/ ...

  5. #linux vscode 保存总提示“Retry as sudo”

    linux中,对不同路径下的文件,系统默认指定了不同的操作权限(读/写/执行),出现这个问题是由于文件的权限不足造成的.(路径为/opt/lampp/htdocs/LearnPHP_jayce/hel ...

  6. Java 14带来了许多新功能

    本文是作者翻译自java magazine的文章,我也将回持续的关注java的最新消息,即时和大家分享.如有翻译不准确的地方,欢迎大家留言,我将第一时间修改.   Java 14包含比前两个发行版更多 ...

  7. C#实现模拟鼠标点击事件(点击桌面的其他程序 )

    注释感觉已经很清楚了,有不懂的欢迎评论 1 using System; using System.Collections.Generic; using System.ComponentModel; u ...

  8. Python3-random模块-生成伪随机数

    Python3中的random模块可以生成一个伪随机数 常用的就三个模块函数 random.random() 返回0-1之间的一个随机数 random.randrange(i, j) 返回一个随机数 ...

  9. openstack迁移计算节点所有云主机

    迁移计算节点所有云主机 -------高德置地 王锦雄   使用host-evacuate-live热迁移主机 查看主机目前的云主机情况 nova hypervisor-servers cloud1 ...

  10. ES6躬行记 笔记

    ES6躬行记(18)--迭代器 要实现以下接口## next() ,return,throw 可以用for-of保证迭代对象的正确性 例如 var str = "向