可持久化并查集

Posted lhm-

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了可持久化并查集相关的知识,希望对你有一定的参考价值。

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

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

(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");//查询

以上是关于可持久化并查集的主要内容,如果未能解决你的问题,请参考以下文章

[bzoj3673][可持久化并查集 by zky] (rope(可持久化数组)+并查集=可持久化并查集)

可持久化并查集

BZOJ-3673&3674可持久化并查集 可持久化线段树 + 并查集

可持久化4--可持久化并查集

[BZOJ 3673]可持久化并查集 by zky

半可持久化并查集