码迷,mamicode.com
首页 > 其他好文 > 详细

可持久化并查集 by zky

时间:2019-11-06 16:56:27      阅读:108      评论:0      收藏:0      [点我收藏+]

标签:tor   clu   ctime   压缩   tac   div   tchar   std   man   

zz:https://www.cnblogs.com/cjoierljl/p/9567859.html

https://www.cnblogs.com/peng-ym/p/9357220.html

n个集合 m个操作
操作:
1 a b 合并a,b所在集合
2 k 回到第k次操作之后的状态(查询算作操作)
3 a b 询问a,b是否属于同一集合,是则输出1否则输出0

0<n,m<=2*10^4

Sample Input

5 6
1 1 2
3 1 2
2 0
3 1 2
2 1
3 1 2

Sample Output

1
0
1

 

#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<iomanip>
#include<algorithm>
#include<ctime>
#include<queue>
#include<stack>
#include<vector>
#define lst long long
#define ldb long double
#define N 200050
#define lson ljl[now].ls
#define rson ljl[now].rs
using namespace std;
const int Inf=1e9;
int read()
{
    int s=0,m=0;char ch=getchar();
    while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)m=1;ch=getchar();}
    while(ch>=‘0‘&&ch<=‘9‘)s=(s<<3)+(s<<1)+(ch^48),ch=getchar();
    return m?-s:s;
}

int n,Q,tot;
int dep[N*30],fa[N*30];
int Edi[N];//版本编号
struct TREE{int ls,rs;}ljl[N*30];
//主席树部分
void Build(int &now,int le,int ri)
{
    if(!now)now=++tot;
    if(le==ri)
	{
		fa[now]=le;
		return;
	}//并查集初始化
    int mid=(le+ri)>>1;
    Build(lson,le,mid);
	Build(rson,mid+1,ri);
}

void Update(int &now,int pre,int le,int ri,int loc,int ff)
//当前版本,上一个版本(复制时要用),左右端点,把loc的爸爸改成ff
{
    now=++tot;//新开log个节点
    if(le==ri)
    {
        dep[now]=dep[pre];
        //因为从前面的版本过来,所以树的深度也要继承
        fa[now]=ff;return;
    }
    lson=ljl[pre].ls,rson=ljl[pre].rs;//把前面的树“复制”过来
    int mid=(le+ri)>>1;
    if(loc<=mid)
	    Update(lson,ljl[pre].ls,le,mid,loc,ff);
    else 
	     Update(rson,ljl[pre].rs,mid+1,ri,loc,ff);
}

int Query(int now,int le,int ri,int loc)
{//找到询问的节点记录的fa[]
    if(le==ri)
	   return now;
    int mid=(le+ri)>>1;
    if(loc<=mid)
	    return Query(lson,le,mid,loc);
    else 
	    return Query(rson,mid+1,ri,loc);
}
//嗯,属于可持久化并查集的特殊部分了
void add(int now,int le,int ri,int loc)
{//按秩合并的树高改变
    if(le==ri)
	{
		dep[now]++;
		return;
	}
    int mid=(le+ri)>>1;
    if(loc<=mid)
	   add(lson,le,mid,loc);
    else 
	   add(rson,mid+1,ri,loc);
}

int Find_fa(int edi,int now)
{
    int ff=Query(edi,1,n,now);//查询在这一版本里now的父亲
    if(now==fa[ff])
	   return ff;
    return Find_fa(edi,fa[ff]);//无路径压缩
}

int main()
{
    n=read(),Q=read();
    Build(Edi[0],1,n);
    for(int i=1;i<=Q;++i)
    {
        int opt=read();
        if(opt==1)
        {
            Edi[i]=Edi[i-1];
            int x=read(),y=read();
            int fx=Find_fa(Edi[i],x),fy=Find_fa(Edi[i],y);
            if(fa[fx]==fa[fy])continue;
            if(dep[fx]>dep[fy])
			   swap(fx,fy);//按秩合并,把x往y合并(dep小的往大的合并)
            Update(Edi[i],Edi[i-1],1,n,fa[fx],fa[fy]);
            if(dep[fx]+1>dep[fy])
			   add(Edi[i],1,n,fa[fy]);
        }
        if(opt==2)
        {
            int kk=read();
            Edi[i]=Edi[kk];
        }
        if(opt==3)
        {
            Edi[i]=Edi[i-1];
            int x=read(),y=read();
            int fx=Find_fa(Edi[i],x),fy=Find_fa(Edi[i],y);
            if(fa[fx]==fa[fy])
			   puts("1");
            else 
			    puts("0");
        }
    }
    return 0;
}

  

可持久化并查集 by zky

标签:tor   clu   ctime   压缩   tac   div   tchar   std   man   

原文地址:https://www.cnblogs.com/cutemush/p/11805932.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!