洛谷P3402 题解

题目链接

\(Solution:\)

我们使用可持久化数组来维护\(x\)\(fa\)的关系
但是朴素的算法会\(TLE\)
所以我们考虑按秩合并,使得树高降到\(logn\)级别

\(Code:\)

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll N=1e5+50;
ll n,m,len,a[N<<5],tmp,pre[N<<5],rt[N<<5],tot;
struct segtree
{
	ll ls,rs,fa,dep;
}tree[N<<5];            
inline ll read()
{
	ll sum=0,f=1;
	char ch=0;
	while(!isdigit(ch))
	{
		if(ch=='-') f=-1;
		ch=getchar();
	}
	while(isdigit(ch))
	{
		sum=(sum<<1)+(sum<<3)+(ch^48);
		ch=getchar();
	}
	return sum*f;
}
inline void build(ll &t,ll l,ll r)
{
	t=++tot;
	if(l==r)
	{
		tree[t].fa=l;
		return ;
	}
	ll mid=(l+r)>>1;
	build(tree[t].ls,l,mid);
	build(tree[t].rs,mid+1,r);
}
inline void merge(ll lst,ll &x,ll l,ll r,ll pos,ll f)
{
	x=++tot;
	tree[x].ls=tree[lst].ls;
	tree[x].rs=tree[lst].rs;
	if(l==r)
	{
		tree[x].fa=f;
		tree[x].dep=tree[lst].dep;
		return ;
	}
	ll mid=(l+r)>>1;
	if(pos<=mid) merge(tree[lst].ls,tree[x].ls,l,mid,pos,f);
	else merge(tree[lst].rs,tree[x].rs,mid+1,r,pos,f);
}
inline void update(ll x,ll l,ll r,ll pos)
{
	if(l==r)
	{
		tree[x].dep++;
		return ;
	} 
	ll mid=(l+r)>>1;
	if(pos<=mid) update(tree[x].ls,l,mid,pos);
	else update(tree[x].rs,mid+1,r,pos);
}
inline ll query(ll x,ll l,ll r,ll pos)
{
	if(l==r) return x;
	ll mid=(l+r)>>1;
	if(pos<=mid) return query(tree[x].ls,l,mid,pos);
	return query(tree[x].rs,mid+1,r,pos);
}
inline ll find(ll x,ll pos)
{
	ll now=query(x,1,n,pos);
	if(tree[now].fa==pos) return now;
	else return find(x,tree[now].fa);
}
int main(void)
{
	n=read(),m=read();
    build(rt[0],1,n);
    for(register ll i=1;i<=m;i++)
	{
        ll op=read(),x=read();
        if(op==1)
		{
            ll y=read();
            rt[i]=rt[i-1];
            ll f1=find(rt[i],x),f2=find(rt[i],y);
            //printf("%d %d\n",f1,f2);
            if(tree[f1].fa!=tree[f2].fa) 
            {
            	if(tree[f1].dep>tree[f2].dep) swap(f1,f2);
            	merge(rt[i-1],rt[i],1,n,tree[f1].fa,tree[f2].fa);
            	if(tree[f1].dep==tree[f2].dep) update(rt[i],1,n,tree[f2].fa);
            }
        }
        else if(op==2)
        {
        	rt[i]=rt[x];
        }
        else if(op==3)
        {
            ll y=read();
            rt[i]=rt[i-1];
            ll f1=find(rt[i],x),f2=find(rt[i],y);
            //printf("%d %d\n",f1,f2);
            if(tree[f1].fa==tree[f2].fa) puts("1");
            else puts("0");
        }
    }
    return 0;
}
posted @ 2020-02-20 11:09  L_G_J  阅读(100)  评论(0编辑  收藏  举报