• 可持久化并查集


    可持久化并查集

    题意

    如题。

    解法

    我们考虑用主席树来维护每一个版本中,x的father,因为我们要做到可持久化, 所以我们不能压缩路径(可能吧) ,我们就需要用到启发式合并。每次将深度较浅的合并到深度较大的集合中,并且,如果两个集合深度相同了的话,将其中的一个深度+1。剩下的就是主席树的基本操作了。

    代码

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    #include <cctype>
    #define INF 2139062143
    #define MAX 0x7ffffffffffffff
    #define del(a,b) memset(a,b,sizeof(a))
    using namespace std;
    typedef long long ll;
    template<typename T>
    inline void read(T&x)
    {
        x=0;T k=1;char c=getchar();
        while(!isdigit(c)){if(c=='-')k=-1;c=getchar();}
        while(isdigit(c)){x=x*10+c-'0';c=getchar();}x*=k;
    }
    const int maxn=1e5+5;
    struct node{
    	int lc,rc,fa,deep;
    }T[maxn*40];
    int root[maxn*2],sz;
    int n,m;
    
    void build(int &x,int l,int r){
    	x=++sz;
    	if(l==r){
    		T[x].fa=l;
    		return;
    	}
    	int mid=(l+r)/2;
    	build(T[x].lc,l,mid);
    	build(T[x].rc,mid+1,r);
    }
    
    void update(int l,int r,int pos,int fa,int &x,int y){
    	T[++sz]=T[y],x=sz;
    	if(l==r) { T[x].fa=fa;return;}
    	int mid=(l+r)/2;
    	if(pos<=mid) update(l,mid,pos,fa,T[x].lc,T[y].lc);
    	else update(mid+1,r,pos,fa,T[x].rc,T[y].rc);
    }
    
    node query(int x,int l,int r,int pos){
    	if(l==r) return T[x];
    	int mid=(l+r)/2;
    	if(pos<=mid) return query(T[x].lc,l,mid,pos);
    	else return query(T[x].rc,mid+1,r,pos);
    }
    
    void add(int x,int l,int r,int pos){
    	if(l==r) { ++T[x].deep;return;}
    	int mid=(l+r)/2;
    	if(pos<=mid) add(T[x].lc,l,mid,pos);
    	else add(T[x].rc,mid+1,r,pos);
    }
    
    node find_fa(int x,int pos){
    	node k=query(x,1,n,pos);
    	if(k.fa==pos) return k;
    	return find_fa(x,k.fa);
    }
    
    void uni(int &x,int y,int pos1,int pos2){
    	x=y;
    	node f1=find_fa(x,pos1),f2=find_fa(x,pos2);
    	if(f1.fa!=f2.fa){
    		if(f1.deep>f2.deep) swap(f1,f2);
    		update(1,n,f1.fa,f2.fa,x,y);
    		if(f1.deep==f2.deep) add(x,1,n,f2.fa);
    	}
    }
    
    int main()
    {
    	read(n),read(m);
    	build(root[0],1,n);
    	for(int i=1;i<=m;i++){
    		int k,x,y;
    		read(k);
    		if(k==1){
    			read(x),read(y);
    			uni(root[i],root[i-1],x,y);
    		}
    		if(k==2){
    			read(x);
    			root[i]=root[x];
    		}
    		if(k==3){
    			read(x),read(y);
    			root[i]=root[i-1];
    			node fa1=find_fa(root[i],x),fa2=find_fa(root[i],y);
    			if(fa1.fa==fa2.fa) printf("1
    ");
    			else printf("0
    ");
    		}
    	}	
    	return 0;
    }
    
  • 相关阅读:
    数据结构 B/B+树
    Hadoop的目录结构
    安装JDK
    OSTEP-projects concurrency-webserver
    第二十四章(制作HTTP服务器端)学习笔记
    day4_生成小数的程序
    day4_用集合生成8位密码的程序
    day4_集合操作
    day3_homework
    day6_random模块的用法、break和continue
  • 原文地址:https://www.cnblogs.com/mrasd/p/9532239.html
Copyright © 2020-2023  润新知