• 可持久化并查集


    合并不采用路径压缩,保证每次合并只修改一个节点的父亲,使当前版本与上一版本共用的节点尽可能的多

    为防止并查集退化成链,采取按秩合并

    (code)

    void build(int L,int R,int &cur)
    {
    	cur=++tree_cnt;
    	if(L==R)
    	{
    		fa[cur]=L;
    		return;
    	}
    	int mid=(L+R)>>1;
    	build(L,mid,ls[cur]);
    	build(mid+1,R,rs[cur]);
    }
    void merge(int L,int R,int pos,int fath,int pre,int &cur)
    {
    	cur=++tree_cnt;
    	if(L==R)
    	{
    		fa[cur]=fath;
    		de[cur]=de[pre];
    		return;
    	}
    	ls[cur]=ls[pre],rs[cur]=rs[pre];
    	int mid=(L+R)>>1;
    	if(pos<=mid) merge(L,mid,pos,fath,ls[pre],ls[cur]);
    	if(pos>mid) merge(mid+1,R,pos,fath,rs[pre],rs[cur]);
    }
    int query(int L,int R,int pos,int cur)
    {
    	if(L==R) return cur;
    	int mid=(L+R)>>1;
    	if(pos<=mid) return query(L,mid,pos,ls[cur]);
    	if(pos>mid) return query(mid+1,R,pos,rs[cur]);
    }
    void add(int L,int R,int pos,int cur)
    {
    	if(L==R)
    	{
    		de[cur]++;
    		return;
    	}
    	int mid=(L+R)>>1;
    	if(pos<=mid) add(L,mid,pos,ls[cur]);
    	else add(mid+1,R,pos,rs[cur]);
    }
    int find(int pos,int cur)
    {
    	int fath=query(1,n,pos,cur);
    	if(pos==fa[fath]) return fath;
    	return find(fa[fath],cur);
    }
    
    ......
    
    read(a),read(b);
    root[i]=root[i-1];
    int u=find(a,root[i]),v=find(b,root[i]);
    if(fa[u]==fa[v]) continue;
    if(de[u]>de[v]) swap(u,v);
    merge(1,n,fa[u],fa[v],root[i-1],root[i]);
    if(de[u]==de[v]) add(1,n,fa[v],root[i]);//合并
    
    read(a);
    root[i]=root[a];//返回历史版本
    
    read(a),read(b);
    root[i]=root[i-1];
    int u=find(a,root[i]),v=find(b,root[i]);
    if(fa[u]==fa[v]) puts("1");
    else puts("0");//查询
    
  • 相关阅读:
    html5基础---canvas
    html5基础---h5特性
    JS常用知识点(一)
    微信小程序开发(一)基础知识学习
    关于C# winform唤起本地已安装应用程序(测试win10,win7可用)
    js原型链结构理解
    JS闭包应用场景之函数回调(含函数的调用个人理解)
    (十三)MySQL锁机制
    (十一)MVCC-多版本并发控制机制(转)
    jvm014-垃圾回收器
  • 原文地址:https://www.cnblogs.com/lhm-/p/12229516.html
Copyright © 2020-2023  润新知