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. Dubbo——SPI及自适应扩展原理

    文章目录 引言 正文 一.什么是SPI? 1. Java SPI的实现 2. Dubbo SPI实现原理 由配置文件得到的猜想 SPI源码 二.自适应扩展机制 三.Dubbo IOC 总结 引言 Du ...

  2. Linux 安装指定jdk版本

    操作步骤 卸载系统自带jdk版本 1.查看安装的jdk rpm -qa | grep java 2.卸载系统自带jdk rpm -e --nodeps 包名 下载jdk 当前最新版本下载地址:http ...

  3. 利用bat文件打开浏览器指定网页,提示 windows找不到chrome.exe。请确定文件名是否正确,再试一次 的解决经历

      1.在网上找到一些bat命令,原来电脑可以正常使用,效果就是执行后打开谷歌浏览器并全屏展示某网页,但是在昨天换个一个电脑后发现不能用了,提示以下截图的错误 2.找了半天发现问题所在: 把chrom ...

  4. 成为python程序员,对疫情过后的毕业生来说,真是一个不错的方向吗?

    Python最近几年,一直被炒得很火,这其中有商业因素,但更重要的是即将到来的人工智能时代,而python就恰好是最适合的编程语言. 所以无论是在职的人,还是在校的学生,都想着跟上这一趋势,但,在今年 ...

  5. WireShark——IP协议包分析(Ping分析IP协议包)

    互联网协议 IP 是 Internet Protocol 的缩写,中文缩写为“网协”.IP 协议是位于 OSI 模型中第三层的协议,其主要目的就是使得网络间能够互联通信.前面介绍了 ARP 协议, 该 ...

  6. 设计模式系列之装饰模式(Decorator Pattern)——扩展系统功能

    说明:设计模式系列文章是读刘伟所著<设计模式的艺术之道(软件开发人员内功修炼之道)>一书的阅读笔记.个人感觉这本书讲的不错,有兴趣推荐读一读.详细内容也可以看看此书作者的博客https:/ ...

  7. elk4

    传统问题: 微服务系统下服务器数量过大,如果还在使用依次登录每台机器的传统方法查询日志,这样效率非常低下.ELK 是elastic公司提供的一套完整的日志收集以及展示的解决方案,是三个产品的首字母缩写 ...

  8. 【转载】张一鸣:为什么 BAT 挖不走我们的人才?

    很多企业失败的时候,总说是政策的变化.市场的变化.消费者需求的变化.技术发展的变化等等,导致了失败,其实这都是瞎说,归根结底还是人的原因,都是因为你招的人不行.可见,人才对于一个企业的重要性. 互联网 ...

  9. python实现将大文件夹分割成多个子文件夹

    楼主用的linux,一旦数据达到几万,文件夹打开就会变卡,同时也方便同时分工协作,便于git管理,写了个将大文件夹分割成多个小文件夹的脚本 如操作文件夹:img,脚本不破坏img的数据,创建img_1 ...

  10. P1640 [SCOI2010]连续攻击游戏【并查集】

    题目描述 lxhgww最近迷上了一款游戏,在游戏里,他拥有很多的装备,每种装备都有2个属性,这些属性的值用[1,10000]之间的数表示.当他使用某种装备时,他只能使用该装备的某一个属性.并且每种装备 ...