可持久化并查集(外传)——[按秩启发式合并]

11 篇文章 0 订阅
3 篇文章 0 订阅

重新开坑

border="0" width="330" height="86" src="//music.163.com/outchain/player?type=3&id=907727144&auto=1&height=66">

奉上最近觉得的神作(至少从小说与这首曲子来说是这样的)。

之前写到过可持久化并查集三部曲,现在想来,唯独没有提到按秩合并,在研习了启发式合并后,决定重新为并查集写一份外传,记录并查集的另一作用。

什么是按秩合并,就小编来看,其实就是启发式合并的一种,在满足不路径压缩改变fa[x]的前提下,能够使得并查集的深度为 logn 级别的。

但是提醒,这里的按秩合并与路径压缩并不矛盾,按秩合并关键在union函数,而路径压缩是在find函数中,若只是普通并查集,就只需要上路径压缩就可以了,应该没有哪个丧尽天良的出题人为了卡路径压缩要求两个优化都用才能AC。。。。

如何实现,先上代码。

int fa[N],f[N];
int siz[N],dpn[N];  
int cnt_merge = 0;  
int find(int x){  
    if(fa[x]==x)return x;  
    int k=findfather(fa[x]);  
    dpn[x]=dpn[fa[x]]+1;//合并时以类似求前缀的方式维护dfn中的值。  
    return k;  
}
inline void merge(int x,int y){  //uniona函数,按秩合并 
    x=find(x),y=find(y);
    if(x==y)return void(++cnt_merge);  
    if(siz[x]>siz[y])fa[y]=x,f[y]=++cnt_merge,siz[x]+= siz[y];  
    else fth[x]=y,f[x]=++cnt_merge,siz[y]+=siz[x];  
}

这样写有什么用呢,或者说为什么这么写?
在两个不同子集连接时,如果我们按照rank来连接,把rank低的连在rank高的下面,让rank高的做father,那么我们就相当于维护了一棵树,保证了类似于启发式合并一样的树高最坏 logn

神奇吧,来一道题清爽一下。

BZOJ4668传送门

//by anantheparty
#include<cstdio>
const int N=5e5+5;
int f[N],d[N],r[N],p[N];
int find(int i){
    if(p[i]==i)return i;
    register int j=find(p[i]);
    d[i]=d[p[i]]+1;
    return j;
}
int unionn(int i,int j){
    i=find(i),j=find(j);
    if(i==j)return 0;
    if(r[i]==r[j])++r[j];
    if(r[i]<r[j]){
        p[i]=j;
        return i;
    }
    p[j]=i;
    return j;
}
int query(int i,int j){
    register int s=0;
    if(find(i)==find(j))
        while(i!=j)
            if(d[i]>d[j])s<f[i]?s=f[i]:0,i=p[i];
            else s<f[j]?s=f[j]:0,j=p[j];
    return s;
}
inline void read(int &res){
    static char ch;
    while((ch=getchar())<'0'||ch>'9');res=ch-48;
    while((ch=getchar())>='0'&&ch<='9')res=res*10+ch-48;
}
int main(){
    register int n,m,k,s,t,last=0;
    read(n),read(m);
    for(;n;--n)p[n]=n;
    while(m--){
        read(k),read(s),read(t);
        s^=last,t^=last;
        if(k)printf("%d\n",last=query(s,t));
        else f[unionn(s,t)]=++n;
    }
    return 0;
}

哈哈我可没有忘记并查集系列的看板娘

这里写图片描述

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值