【BZOJ】【3673】可持久化并查集 & 【3674】可持久化并查集加强版
可持久化并查集
Orz hzwer & zyf
呃学习了一下可持久化并查集的姿势……其实并查集就是一个fa数组(可能还要带一个size或rank数组),那么我们对并查集可持久化其实就是实现一个可持久化数组……
那么我们用可持久化线段树实现一下可持久化数组就可以了- -
一开始我比较傻逼,想着:中间的叶子节点不是没用嘛?什么信息也不存……然而如果不这样的话,难道你每次修改,新建N个指针吗?这样可以保证每次只新建O(logn)个节点出来……
(是不是a+b problem也是类似的原因?并不知道诶……去做下看看好了)
嘛那么这里维护一下fa和size就可以了。。。
/**************************************************************
Problem: 3673
User: Tunix
Language: C++
Result: Accepted
Time:64 ms
Memory:7608 kb
****************************************************************/ //BZOJ 3673
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define rep(i,n) for(int i=0;i<n;++i)
#define F(i,j,n) for(int i=j;i<=n;++i)
#define D(i,j,n) for(int i=j;i>=n;--i)
#define pb push_back
using namespace std;
typedef long long LL;
inline int getint(){
int r=,v=; char ch=getchar();
for(;!isdigit(ch);ch=getchar()) if (ch=='-') r=-;
for(; isdigit(ch);ch=getchar()) v=v*-''+ch;
return r*v;
}
const int N=2e4+;
/*******************template********************/ int n,m,cnt,rt[N]; struct node{
int l,r,v,size;
}t[N*];
#define L t[o].l
#define R t[o].r
#define mid (l+r>>1)
#define lch L,l,mid
#define rch R,mid+1,r void build(int &o,int l,int r){
o=++cnt;
if (l==r) {t[o].v=l;t[o].size=;return;}
build(lch);
build(rch);
}
void update(int &o,int l,int r,int pos,int v){
t[++cnt]=t[o], o=cnt;
if (l==r) {t[o].v=v; return;}
if (pos<=mid) update(lch,pos,v);
else update(rch,pos,v);
}
void modify(int &o,int l,int r,int pos,int v){
t[++cnt]=t[o], o=cnt;
if (l==r) {t[o].size+=v; return;}
if (pos<=mid) modify(lch,pos,v);
else modify(rch,pos,v);
}
int queryv(int o,int l,int r,int pos){
if (l==r) return t[o].v;
if (pos<=mid) return queryv(lch,pos);
else return queryv(rch,pos);
}
int querysz(int o,int l,int r,int pos){
if (l==r) return t[o].size;
if (pos<=mid) return querysz(lch,pos);
else return querysz(rch,pos);
}
int getfa(int x,int y){
int now=y,nxt=queryv(rt[x],,n,y);
while(now!=nxt){
now=nxt;
nxt=queryv(rt[x],,n,now);
}
return now;
} int main(){
#ifndef ONLINE_JUDGE
freopen("3673.in","r",stdin);
freopen("3673.out","w",stdout);
#endif
n=getint(); m=getint();
build(rt[],,n);
int cmd,x,y,ans=;
F(i,,m){
rt[i]=rt[i-];
cmd=getint();
if (cmd==){
x=getint(); y=getint();
int f1=getfa(i,x),f2=getfa(i,y),
s1=querysz(rt[i],,n,f1),s2=querysz(rt[i],,n,f2);
if (s1<s2) swap(f1,f2);
modify(rt[i],,n,f1,s2);
update(rt[i],,n,f2,f1);
}else if (cmd==){
rt[i]=rt[getint()];
}else if (cmd==){
x=getint(); y=getint();
int f1=getfa(i,x),f2=getfa(i,y);
printf("%d\n",ans=(f1==f2));
}
}
return ;
}
(3673)
/**************************************************************
Problem: 3674
User: Tunix
Language: C++
Result: Accepted
Time:1336 ms
Memory:158308 kb
****************************************************************/ //BZOJ 3674
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define rep(i,n) for(int i=0;i<n;++i)
#define F(i,j,n) for(int i=j;i<=n;++i)
#define D(i,j,n) for(int i=j;i>=n;--i)
#define pb push_back
using namespace std;
typedef long long LL;
inline int getint(){
int r=,v=; char ch=getchar();
for(;!isdigit(ch);ch=getchar()) if (ch=='-') r=-;
for(; isdigit(ch);ch=getchar()) v=v*-''+ch;
return r*v;
}
const int N=2e5+;
/*******************template********************/ int n,m,cnt,rt[N]; struct node{
int l,r,v,size;
}t[];
#define L t[o].l
#define R t[o].r
#define mid (l+r>>1)
#define lch L,l,mid
#define rch R,mid+1,r void build(int &o,int l,int r){
o=++cnt;
if (l==r) {t[o].v=l;t[o].size=;return;}
build(lch);
build(rch);
}
void update(int &o,int l,int r,int pos,int v){
t[++cnt]=t[o], o=cnt;
if (l==r) {t[o].v=v; return;}
if (pos<=mid) update(lch,pos,v);
else update(rch,pos,v);
}
void modify(int &o,int l,int r,int pos,int v){
t[++cnt]=t[o], o=cnt;
if (l==r) {t[o].size+=v; return;}
if (pos<=mid) modify(lch,pos,v);
else modify(rch,pos,v);
}
int queryv(int o,int l,int r,int pos){
if (l==r) return t[o].v;
if (pos<=mid) return queryv(lch,pos);
else return queryv(rch,pos);
}
int querysz(int o,int l,int r,int pos){
if (l==r) return t[o].size;
if (pos<=mid) return querysz(lch,pos);
else return querysz(rch,pos);
}
int getfa(int x,int y){
int now=y,nxt=queryv(rt[x],,n,y);
while(now!=nxt){
now=nxt;
nxt=queryv(rt[x],,n,now);
}
return now;
} int main(){
#ifndef ONLINE_JUDGE
freopen("3674.in","r",stdin);
freopen("3674.out","w",stdout);
#endif
n=getint(); m=getint();
build(rt[],,n);
int cmd,x,y,ans=;
F(i,,m){
rt[i]=rt[i-];
cmd=getint();
if (cmd==){
x=getint()^ans; y=getint()^ans;
int f1=getfa(i,x),f2=getfa(i,y),
s1=querysz(rt[i],,n,f1),s2=querysz(rt[i],,n,f2);
if (s1<s2) swap(f1,f2);
modify(rt[i],,n,f1,s2);
update(rt[i],,n,f2,f1);
}else if (cmd==){
rt[i]=rt[getint()^ans];
}else if (cmd==){
x=getint()^ans; y=getint()^ans;
int f1=getfa(i,x),f2=getfa(i,y);
printf("%d\n",ans=(f1==f2));
}
}
return ;
}
(3674)
(3674为强制在线,且数据范围20W)
3673: 可持久化并查集 by zky
Time Limit: 5 Sec Memory Limit: 128 MB
Submit: 757 Solved: 319
[Submit][Status][Discuss]
Description
n个集合 m个操作
操作:
1 a b 合并a,b所在集合
2 k 回到第k次操作之后的状态(查询算作操作)
3 a b 询问a,b是否属于同一集合,是则输出1否则输出0
0<n,m<=2*10^4
Input
Output
Sample Input
1 1 2
3 1 2
2 0
3 1 2
2 1
3 1 2
Sample Output
0
1
HINT
Source
【BZOJ】【3673】可持久化并查集 & 【3674】可持久化并查集加强版的更多相关文章
- bzoj 3673&3674 可持久化并查集&加强版(可持久化线段树+启发式合并)
CCZ在2015年8月25日也就是初三暑假要结束的时候就已经能切这种题了%%% 学习了另一种启发式合并的方法,按秩合并,也就是按树的深度合并,实际上是和按树的大小一个道理,但是感觉(至少在这题上)更好 ...
- BZOJ.3673/3674.可持久化并查集(可持久化线段树 按秩合并/启发式合并)
BZOJ 3673 BZOJ 3674(加强版) 如果每次操作最多只修改一个点的fa[],那么我们可以借助可持久化线段树来O(logn)做到.如果不考虑找fa[]的过程,时空复杂度都是O(logn). ...
- [bzoj] 3673 3674 可持久化并查集 || 可持久化数组
原题 加强版 题意: 可持久化并查集模板-- 题解: 用可持久化线段树维护一个可持久化数组,来记录每一次操作后的状态. 不能用路径压缩,但是要按置合并,使复杂度保证在O(log) #include&l ...
- BZOJ 3673 可持久化并查集 by zky && BZOJ 3674 可持久化并查集加强版 可持久化线段树
既然有了可持久化数组,就有可持久化并查集.. 由于上课讲过说是只能按秩合并(但是我也不确定...),所以就先写了按秩合并,相当于是维护fa[]和rk[] getf就是在这棵树中找,直到找到一个点的fa ...
- bzoj 3674: 可持久化并查集加强版 (启发式合并+主席树)
Description Description:自从zkysb出了可持久化并查集后……hzwer:乱写能AC,暴力踩标程KuribohG:我不路径压缩就过了!ndsf:暴力就可以轻松虐!zky:…… ...
- BZOJ 3674 可持久化并查集加强版(路径压缩版本)
/* bzoj 3674: 可持久化并查集加强版 http://www.lydsy.com/JudgeOnline/problem.php?id=3674 用可持久化线段树维护可持久化数组从而实现可持 ...
- BZOJ 3674 可持久化并查集加强版(按秩合并版本)
/* bzoj 3674: 可持久化并查集加强版 http://www.lydsy.com/JudgeOnline/problem.php?id=3674 用可持久化线段树维护可持久化数组从而实现可持 ...
- Bzoj 3673: 可持久化并查集 by zky(主席树+启发式合并)
3673: 可持久化并查集 by zky Time Limit: 5 Sec Memory Limit: 128 MB Description n个集合 m个操作 操作: 1 a b 合并a,b所在集 ...
- Redis的增删改查命令总结与持久化方式
原文:Redis的增删改查命令总结与持久化方式 Redis是用C语言实现的,一般来说C语言实现的程序"距离"操作系统更近,执行速度相对会更快. Redis使用了单线程架构,预防了多 ...
- 05[掌握]高可用、集群、持久化、docker 等前置知识点
高可用 24小时对外提供服务 高并发 同一时间段能处理的请求数 1,中心化和去中心化 1.1,中心化 意思是所有的节点都要有一个主节点 缺点:中心挂了,服务就挂了 中心处理数据的能力有限,不能把节点性 ...
随机推荐
- 002.iSCSI服务端配置
一 iSCSI target的磁盘种类 大型文件 单一分区(partition) 磁盘 数组 RAID LVM 二 iSCSI创建步骤 建立用于共享的磁盘设备(分区/磁盘/文件) 创建后备磁盘 创建相 ...
- 001.SSH配置文件
一 ssh配置文件路径 1.1 ssh客户端配置文件: 路径:/etc/ssh/ssh_config 1.2 ssh服务端配置文件: 路径:/etc/ssh/sshd_config 二 服务器端常用配 ...
- auth.User.groups: (fields.E304)
配置用户信息的models时,如果继承Abstractuser类时,报错: ERRORS:auth.User.groups: (fields.E304) Reverse accessor for 'U ...
- Windows栈溢出原理
1.栈是什么? 栈是一种运算受限的线性表 其限制是仅允许在表的一端进行插入和删除运算 这一端称为栈顶(TOP),相对的另一端称为栈底(BASE) 向一个栈插入新元素,称作进栈.入栈或压栈(PUSH) ...
- mysql索引原理剖析
一.索引的原理 所谓索引,即是快速定位与查找,那么索引的结构组织要尽量减少查找过程中磁盘I/O的存取次数(B+树相比B树,其非叶子节点占用更小的空间,可以有更多非叶子节点存放在再内存中,减少大量的IO ...
- android 多进程
韩梦飞沙 韩亚飞 313134555@qq.com yue31313 han_meng_fei_sha android应用中 可以通过 清单文件的属性配置,创建出一个新进程. 多进程的好处,当 ...
- Hdu5385 The path
The path Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Su ...
- Activator 动态构造对象
Activator 意义: 用于动态构造对象 语法1: 根据指定的泛型类型构造对象 Activator.CreateInstance<类型>() 语法2: 根据程序集和类型名构造对象 S ...
- asp.net core中的razor页面
Razor 页面(Razor Pages)是 ASP.NET Core 2.0 中新增的一种Web页面模型,相对MVC形式更加简单易用,可以说是一个服务端的MVVM模型,本文简单的介绍一下它的用法. ...
- 《Go语言实战》摘录:6.4 并发 - 锁住共享资源
6.4 锁住共享资源