【BZOJ】3673: 可持久化并查集 by zky

传送门 http://www.lydsy.com/JudgeOnline/problem.php?id=3673

可持久化数据结构去搞下father数组就好

我写了线段树,除了叶子什么都不维护,树的形态只供路径的导向

#include<stdio.h> 
#include<algorithm> 
#define N 20005 
using namespace std; 
   
struct tree{int f,s,lson,rson;}t[N<<5]; 
   
int n,m,c2,tot,fu,fv,aim,s1,s2,type,u,v,Rt[N]; 
bool flag; 
   
void build(int &k,const int &l,const int &r) 
{ 
    k=++tot; 
    if (l==r){t[k]=(tree){l,1,0,0};return;} 
    int mid=l+r>>1; 
    build(t[k].lson,l,mid); 
    build(t[k].rson,mid+1,r); 
} 
   
int fa(const int &k,const int &l,const int &r) 
{ 
    if (l==r) 
    { 
        aim=t[k].f; 
        if (t[k].f==l) flag=1; 
        return t[k].s; 
    } 
    int mid=l+r>>1,rt; 
    while (!flag && l<=aim && aim<=r) rt=(aim<=mid)?fa(t[k].lson,l,mid):fa(t[k].rson,mid+1,r); 
    return rt; 
} 
   
void change(int &k,const int &l,const int &r) 
{ 
    if (!k) k=++tot; 
    if (l==r){t[k]=(tree){fu,c2,0,0};return;} 
    int mid=l+r>>1; 
    if (aim<=mid){change(t[k].lson,l,mid);return;} 
    change(t[k].rson,mid+1,r); 
} 
   
void link(const int &k,const int &lk,const int &l,const int &r) 
{ 
    if (l==r) return; 
    if (!t[k].lson) t[k].lson=t[lk].lson; 
    if (!t[k].rson) t[k].rson=t[lk].rson; 
    int mid=l+r>>1; 
    if (aim<=mid){link(t[k].lson,t[lk].lson,l,mid);return;} 
    link(t[k].rson,t[lk].rson,mid+1,r); 
} 
   
int main() 
{ 
    scanf("%d%d",&n,&m); 
    build(Rt[0],1,n); 
    for (int i=1;i<=m;i++) 
    { 
        scanf("%d",&type);
        if (type==1) 
        { 
            scanf("%d%d",&u,&v); 
            flag=0,aim=u,s1=fa(Rt[i-1],1,n),fu=aim; 
            flag=0,aim=v,s2=fa(Rt[i-1],1,n),fv=aim;
            if (fu!=fv)
            {
                if (s1<s2) swap(fu,fv); 
                c2=s1+s2,aim=fu,change(Rt[i],1,n); 
                c2=s2,aim=fv,change(Rt[i],1,n); 
                aim=fu,link(Rt[i],Rt[i-1],1,n); 
                aim=fv,link(Rt[i],Rt[i-1],1,n); 
            }
            else Rt[i]=Rt[i-1];
        } 
        if (type==2) 
        { 
            scanf("%d",&u); 
            Rt[i]=Rt[u]; 
        } 
        if (type==3) 
        { 
            scanf("%d%d",&u,&v);
            Rt[i]=Rt[i-1]; 
            flag=0,aim=u,s1=fa(Rt[i],1,n),fu=aim; 
            flag=0,aim=v,s2=fa(Rt[i],1,n),fv=aim; 
            printf("%d\n",fu==fv?1:0);  
        } 
    } 
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值