BZOJ 3674 主席树+并查集

/*
    BZOJ 3674: 可持久化并查集加强版

    主席树+并查集
*/
#include <cstdio>
#include <algorithm>

#define m (l+r)/2
using namespace std;

const int N = 200100;
const int M = N * 60;

int n,q,tot;
int fa[M],dp[M],T[N*4],lson[M],rson[M];

int init(int l,int r){
    int root=tot++;
    if(l==r)fa[root]=l,dp[root]=0;
    else lson[root]=init(l,m),rson[root]=init(m+1,r);
    return root;
}
int read(){
    int x=0;char ch=getchar();
    while(ch>'9'||ch<'0')ch=getchar();
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x;
}
int upd(int root,int pos,int val,int tag){//printf("%d%d%d\n",tag,pos,val);
    int l=1,r=n,ret=tot++,cur=ret;
    while(r>l){
        if(pos<=m){
            r=m;
            rson[cur]=rson[root];
            cur=lson[cur]=tot++;
            root=lson[root];
        }
        else{
            l=m+1;
            lson[cur]=lson[root];
            cur=rson[cur]=tot++;
            root=rson[root];
        }
    }
    fa[cur]=fa[root];dp[cur]=dp[root];
    if(tag==0)fa[cur]=val;
    else dp[cur]=val;
    return ret;
}
int get(int root,int pos,int tag){
    int l=1,r=n;
    while(r>l){
        if(pos<=m)r=m,root=lson[root];
        else l=m+1,root=rson[root];
    }
    if(tag)return dp[root];
    return fa[root];
}
int get_fa(int root,int pos){
    int tmp=pos;
    while((tmp=get(root,tmp,0))!=pos)pos=tmp;
    return tmp;
}

int main(){
    while(~scanf("%d%d",&n,&q))
    {
        tot=0;
        T[0]=init(1,n);
        int ans=0;
        for(int i=1;i<=q;i++){
            int p,a,b;  //b=1;
            p=read();a=read();
            if(p==2){
                a^=ans;
                T[i]=T[a];
            }
            if(p==1){
                b=read();
                a^=ans;b^=ans;
                T[i]=T[i-1];
                int fa=get_fa(T[i],a),fb=get_fa(T[i],b);
                if(fa!=fb){
                    int dpa=get(T[i],fa,1),dpb=get(T[i],fb,1);
                    if(dpa<dpb)swap(dpa,dpb),swap(fa,fb);
                    T[i]=upd(T[i],fb,fa,0);
                    if(dpa==dpb)T[i]=upd(T[i],fa,dpa+1,1);
                }
            }
            if(p==3){
                b=read();
                a^=ans;b^=ans;
                T[i]=T[i-1];
                ans=(get_fa(T[i],a)==get_fa(T[i],b));
                printf("%d\n",ans);
            }
        }
    }
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值