[BZOJ 3673&BZOJ 3674]可持久化并查集以及加强版 by zky(主席树)

Description

n个集合 m个操作
操作:
1 a b 合并a,b所在集合
2 k 回到第k次操作之后的状态(查询算作操作)
3 a b 询问a,b是否属于同一集合,是则输出1否则输出0

Solution

用主席树维护一个可持久化的数组来进行并查集操作

并查集按秩合并

一开始没有路径压缩,果然被加强版卡掉了,然后改了改代码,RE了几发(于是AC率又下降了1%)

发现数组开小了…!@#¥%…&*

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#define MAXN 200005
using namespace std;
int n,m,tot=0;
int rt[MAXN],ls[MAXN*50],rs[MAXN*50],f[MAXN*50],h[MAXN*50];
int read()
{
    int x=0,f=1;char c=getchar();
    while(c<'0'||c>'9'){
        if(c=='-')f=-1;c=getchar();
    }
    while(c>='0'&&c<='9'){
        x=x*10+c-'0';c=getchar();
    }
    return x*f;
}
void build(int &idx,int l,int r)
{
    tot++,idx=tot;
    if(l==r){f[idx]=l,h[idx]=0;return;}
    int mid=(l+r)>>1;
    build(ls[idx],l,mid);
    build(rs[idx],mid+1,r);
}
int query(int idx,int l,int r,int x)
{
    if(l==r)return idx;
    int mid=(l+r)>>1;
    if(x<=mid)return query(ls[idx],l,mid,x);
    else return query(rs[idx],mid+1,r,x);
}
void insert(int &idx,int last,int l,int r,int pos,int x)
{
    tot++,idx=tot;
    ls[idx]=ls[last],rs[idx]=rs[last];
    if(l==r){f[idx]=x;h[idx]=h[last];return;}
    int mid=(l+r)>>1;
    if(pos<=mid)insert(ls[idx],ls[last],l,mid,pos,x);
    else insert(rs[idx],rs[last],mid+1,r,pos,x);
}
int find(int &idx,int last,int x)
{
    int t=query(idx,1,n,x);
    if(f[t]==x)return t;
    int p=find(idx,last,f[t]);
    insert(idx,last,1,n,x,f[p]);
    return p;
}
int main()
{
    n=read(),m=read();
    build(rt[0],1,n);
    int opt,a,b,k,x,y,key=0;
    for(int i=1;i<=m;i++)
    {
        opt=read();
        switch(opt)
        {
            case 1:
                a=read(),b=read();
                a^=key,b^=key;
                rt[i]=rt[i-1];
                x=find(rt[i],rt[i-1],a),y=find(rt[i],rt[i-1],b);
                if(f[x]==f[y])continue;
                if(h[x]==h[y])h[x]++;
                if(h[x]<h[y])swap(x,y);
                insert(rt[i],rt[i-1],1,n,f[y],f[x]);
                break;
            case 2:
                k=read();
                k^=key;
                rt[i]=rt[k];
                break;
            case 3:
                a=read(),b=read();
                a^=key,b^=key;
                rt[i]=rt[i-1];
                x=find(rt[i],rt[i-1],a),y=find(rt[i],rt[i-1],b);
                if(f[x]==f[y]){printf("1\n");key=1;}
                else {printf("0\n");key=0;}
                break;
        }
    }
    return 0;
} 

 

posted @ 2017-04-28 01:00  Zars19  阅读(148)  评论(2编辑  收藏  举报