P3402 【模板】可持久化并查集 主席树

  

题目描述

n个集合 m个操作

操作:

  • 1 a b 合并a,b所在集合

  • 2 k 回到第k次操作之后的状态(查询算作操作)

  • 3 a b 询问a,b是否属于同一集合,是则输出1否则输出0

输入格式

输出格式

输入输出样例

输入 #1
5 6
1 1 2
3 1 2
2 0
3 1 2
2 1
3 1 2
输出 #1
1
0
1



主席树维护即可 注意启发式合并
#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define repp(i,a,b) for(int i=(a);i>=(b);--i)
#define ll long long
#define see(x) (cerr<<(#x)<<'='<<(x)<<endl)
#define pb push_back
#define inf 0x3f3f3f3f
#define CLR(A,v)  memset(A,v,sizeof A)
typedef pair<int,int>pii;
//////////////////////////////////
const int N=2e6+10;

int T[N],t[N<<5],lson[N<<5],rson[N<<5],dep[N<<5],n,m,op,a,b,c,ncnt;

void build(int l,int r,int &pos)
{
    pos=++ncnt;
    if(l==r){t[pos]=l;return ;}
    int m=(l+r)>>1;
    build(l,m,lson[pos]);
    build(m+1,r,rson[pos]);
}
void upnode(int x,int fa,int l,int r,int pre,int &pos)
{
    pos=++ncnt;t[pos]=t[pre];lson[pos]=lson[pre];rson[pos]=rson[pre];
    if(l==r){t[pos]=fa;dep[pos]=dep[pre];return ;}
    int m=(l+r)>>1;
    if(x<=m)upnode(x,fa,l,m,lson[pos],lson[pos]);
    else upnode(x,fa,m+1,r,rson[pos],rson[pos]);
}
int qsum(int x,int l,int r,int pos)
{
    if(l==r)return pos;
    int m=(l+r)>>1;
    if(x<=m)return qsum(x,l,m,lson[pos]);
    else return qsum(x,m+1,r,rson[pos]);
}
void adddep(int x,int l,int r,int pos)
{
    if(l==r){dep[pos]++;return ;}
    int m=(l+r)>>1;
    if(x<=m)adddep(x,l,m,lson[pos]);
    else adddep(x,m+1,r,rson[pos]);
}
int find1(int x,int tt)
{
    int pos=qsum(x,1,n,tt);
    if(t[pos]==x)return pos;
    return find1(t[pos],tt);
}
int main()
{
    cin>>n>>m;
    build(1,n,T[0]);
    rep(i,1,m)
    {
        cin>>op;
        if(op==1)
        {
            cin>>a>>b;
            T[i]=T[i-1];
            int x=find1(a,T[i]),y=find1(b,T[i]);
            if(t[x]==t[y])continue;
            if(dep[x]>dep[y])swap(x,y);
            upnode(t[x],t[y],1,n,T[i-1],T[i]);
            if(dep[x]==dep[y])adddep(y,1,n,T[i]);
        }
        else if(op==2)
        {
            int k;cin>>k;
            T[i]=T[k];
        }
        else
        {
            T[i]=T[i-1];
            cin>>a>>b;
            if( t[find1(a,T[i])]==t[find1(b,T[i])] )
                printf("1\n");
            else printf("0\n");
        }
    }
    return 0;
}
View Code



猜你喜欢

转载自www.cnblogs.com/bxd123/p/11344357.html