博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
可持久化并(xian)查(duan)集(shu)
阅读量:5163 次
发布时间:2019-06-13

本文共 4742 字,大约阅读时间需要 15 分钟。

随便地点开了这道可持久化并查集,发现了真相...这和并查集有 PI 关系哦.除了find_father(而且还不能路径压缩),全都是线段树0.0

 

题目链接:

题目没什么描述,就是三个操作:

1. 合并 a b

2. 回到第 k 步操作(三个操作均算操作)

3. 查询 a b 在当前版本的并查集中是否在同一棵树中

 

那么...

对于操作 1 :我们在线段树中修改节点 fa 的父亲为 fb

 

对于操作 2 :简单,我们直接把当前版本的根指向第 k 版本的根,一行就解决了(引起可持久化的罪魁祸首解决倒是简单)

 

 

对于操作 3 :查询 fafb 输出就好了(貌似就操作 1 有点不好理解

 

 

对于操作 1 ,模拟如图:

 

 

 

代码如下:

 

1 //by Judge 2 #include
3 #include
4 #include
5 #include
6 #define ls ch[now][0] 7 #define rs ch[now][1] 8 #define mid (l+r>>1) 9 #define swap(a,b) (a)^=(b)^=(a)^=(b)10 using namespace std;11 const int M=2e5+11; 12 inline int read(){13 int x=0,f=1; char c=getchar();14 for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;15 for(;isdigit(c);c=getchar()) x=x*10+c-'0';16 return x*f;17 }18 int n,m,cnt;19 int ed[M<<5],f[M<<5],ch[M<<5][2],dep[M<<5];20 inline void build(int& now,int l,int r){ //建树,叶子节点认 左(右)端点 为父亲21 now=++cnt; if(l==r){ f[now]=l; return ; }22 build(ls,l,mid), build(rs,mid+1,r);23 }24 void update(int& now,int las,int l,int r,int pos,int fa){ //修改 pos 的父亲为 fa25 now=++cnt; if(l==r){ f[now]=fa,dep[now]=dep[las]; return ; }26 if(pos<=mid) update(ls,ch[las][0],l,mid,pos,fa);27 else update(rs,ch[las][1],mid+1,r,pos,fa);28 }29 int query(int now,int l,int r,int pos){ //询问在 now 版本中 pos 的节点编号30 if(l==r) return now;31 if(pos<=mid) return query(ls,l,mid,pos);32 else return query(rs,mid+1,r,pos);33 }34 void add(int now,int l,int r,int pos){ //增加 now 版本中 pos 所在叶子节点的深度35 if(l==r) { ++dep[now]; return ; }36 if(pos<=mid) add(ls,l,mid,pos);37 else add(rs,mid+1,r,pos);38 }39 int find(int ed,int x){ //查询祖先40 int fa=query(ed,1,n,x);41 if(x==f[fa]) return fa;42 return find(ed,f[fa]);43 }44 int main(){45 n=read(),m=read(),build(ed[0],1,n);46 for(int i=1,opt,a,b,f1,f2;i<=m;++i)47 switch(opt=read()){48 case 1: //不显然49 ed[i]=ed[i-1],a=read(),b=read();50 f1=find(ed[i],a),f2=find(ed[i],b);51 if(f[f1]==f[f2]) break;52 if(dep[f1]>dep[f2]) swap(f1,f2);53 update(ed[i],ed[i-1],1,n,f[f1],f[f2]);54 if(dep[f1]==dep[f2]) add(ed[i],1,n,f[f2]); break; //这里 emmm,看上文55 case 2: //显然56 ed[i]=ed[read()]; break;57 case 3: //显然58 ed[i]=ed[i-1],a=read(),b=read();59 f1=find(ed[i],a), f2=find(ed[i],b);60 puts(f[f1]==f[f2]?"1":"0"); break;61 }62 return 0;63 }

 

上面代码可能出锅,下面代码应该没毛病...

 

1 //by Judge 2 #include
3 #include
4 #include
5 #include
6 #define ls ch[now][0] 7 #define rs ch[now][1] 8 #define mid (l+r>>1) 9 #define swap(a,b) (a)^=(b)^=(a)^=(b)10 using namespace std;11 const int M=2e5+11; 12 inline int read(){13 int x=0,f=1; char c=getchar();14 for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;15 for(;isdigit(c);c=getchar()) x=x*10+c-'0';16 return x*f;17 }18 int n,m,cnt;19 int ed[M<<5],f[M<<5],ch[M<<5][2],dep[M<<5];20 inline void build(int& now,int l,int r){21 now=++cnt; if(l==r){ f[now]=l; return ; }22 build(ls,l,mid), build(rs,mid+1,r);23 }24 void update(int& now,int las,int l,int r,int pos,int fa){25 now=++cnt; if(l==r){ f[now]=fa,dep[now]=dep[las]; return ; }26 ls=ch[las][0], rs=ch[las][1];27 if(pos<=mid) update(ls,ch[las][0],l,mid,pos,fa);28 else update(rs,ch[las][1],mid+1,r,pos,fa);29 }30 int query(int now,int l,int r,int pos){31 if(l==r) return now;32 if(pos<=mid) return query(ls,l,mid,pos);33 else return query(rs,mid+1,r,pos);34 }35 void add(int now,int l,int r,int pos){36 if(l==r) { ++dep[now]; return ; }37 if(pos<=mid) add(ls,l,mid,pos);38 else add(rs,mid+1,r,pos);39 }40 int find(int ed,int x){41 int fa=query(ed,1,n,x);42 if(x==f[fa]) return fa;43 return find(ed,f[fa]);44 }45 int main(){46 n=read(),m=read(),build(ed[0],1,n);47 for(int i=1,opt,a,b,f1,f2;i<=m;++i)48 switch(opt=read()){49 case 1:50 ed[i]=ed[i-1],a=read(),b=read();51 f1=find(ed[i],a),f2=find(ed[i],b);52 if(f[f1]==f[f2]) break;53 if(dep[f1]>dep[f2]) swap(f1,f2);54 update(ed[i],ed[i-1],1,n,f[f1],f[f2]);55 if(dep[f1]==dep[f2]) add(ed[i],1,n,f[f2]); break;56 case 2: ed[i]=ed[read()]; break;57 case 3:58 ed[i]=ed[i-1],a=read(),b=read();59 f1=find(ed[i],a), f2=find(ed[i],b);60 puts(f[f1]==f[f2]?"1":"0"); break;61 }62 return 0;63 }

 

 

 by Judge

转载于:https://www.cnblogs.com/Judge/p/9441179.html

你可能感兴趣的文章
Linq to Object实现分页获取数据
查看>>
mac常用系统命令
查看>>
第42章:MongoDB-集群--Sharding(分片)--单机的搭建
查看>>
2016/11/14
查看>>
异步执行js脚本——防止阻塞
查看>>
利用Excel导出sql语句
查看>>
配置懒人框架——Android annotation
查看>>
伪分布模式安装hadoop
查看>>
oracle 051学习笔记
查看>>
Leanote 二进制版详细安装教程 Windows
查看>>
用 ROS 做内网DNS服务器
查看>>
算法 - 求和为n的连续正整数序列(C++)
查看>>
这些哭笑不得的情景,每一个程序猿都可能面对
查看>>
APUE学习笔记——10.15 sigsetjmp和siglongjmp
查看>>
Codeforces 455B A Lot of Games(字典树+博弈)
查看>>
经验19--C#大事
查看>>
基于Visual Studio .NET2015的单元测试 OpenCover
查看>>
浙江大学PAT上机题解析之2-06. 数列求和
查看>>
Errors
查看>>
(生活)没有好天气
查看>>