BZOJ 3673: 可持久化并查集 by zky
Posted NeighThorn
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ 3673: 可持久化并查集 by zky相关的知识,希望对你有一定的参考价值。
3673: 可持久化并查集 by zky
Time Limit: 5 Sec Memory Limit: 128 MBSubmit: 2084 Solved: 941
[Submit][Status][Discuss]
Description
n个集合 m个操作
操作:
1 a b 合并a,b所在集合
2 k 回到第k次操作之后的状态(查询算作操作)
3 a b 询问a,b是否属于同一集合,是则输出1否则输出0
0<n,m<=2*10^4
Input
Output
Sample Input
5 6
1 1 2
3 1 2
2 0
3 1 2
2 1
3 1 2
1 1 2
3 1 2
2 0
3 1 2
2 1
3 1 2
Sample Output
1
0
1
0
1
HINT
Source
分析:
因为我们需要回溯到历史版本所以需要把并查集可持久化,所以我们用可持久化线段树维护一个可持久化的数组,支持单点修改单点查询...数组中维护的是fa和siz...
代码:
#include<algorithm> #include<iostream> #include<cstring> #include<cstdio> //by NeighThorn using namespace std; const int maxn=20000+5,maxm=5000000+5; int n,m,tot,ls[maxm],rs[maxm],fa[maxm],siz[maxm],root[maxn]; inline void build(int &x,int l,int r){ x=++tot;int mid=(l+r)>>1; if(l==r){ siz[x]=1,fa[x]=l; return; } build(ls[x],l,mid);build(rs[x],mid+1,r); } inline void change(int l,int r,int x,int &y,int pos,int val){ y=++tot; if(l==r){ fa[y]=val,siz[y]=siz[x]; return; } int mid=(l+r)>>1;ls[y]=ls[x];rs[y]=rs[x]; if(pos<=mid) return change(l,mid,ls[x],ls[y],pos,val); else return change(mid+1,r,rs[x],rs[y],pos,val); } inline void add(int l,int r,int x,int pos,int val){ if(l==r){ siz[x]+=val; return; } int mid=(l+r)>>1; if(pos<=mid) add(l,mid,ls[x],pos,val); else add(mid+1,r,rs[x],pos,val); } inline int query(int l,int r,int x,int pos){ if(l==r) return x; int mid=(l+r)>>1; if(pos<=mid) return query(l,mid,ls[x],pos); else return query(mid+1,r,rs[x],pos); } inline int find(int rt,int x){ int f=query(1,n,rt,x); if(fa[f]==x) return f; return find(rt,fa[f]); } signed main(void){ scanf("%d%d",&n,&m);build(root[0],1,n); for(int i=1,opt,x,y;i<=m;i++){ scanf("%d",&opt); if(opt==1){ scanf("%d%d",&x,&y);root[i]=root[i-1]; int fx=find(root[i],x),fy=find(root[i],y); if(fa[fx]==fa[fy]) continue; if(siz[fx]>siz[fy]) swap(fx,fy); change(1,n,root[i-1],root[i],fa[fx],fa[fy]),add(1,n,root[i],fa[fy],siz[fx]); } else if(opt==2) scanf("%d",&x),root[i]=root[x]; else{ scanf("%d%d",&x,&y),root[i]=root[i-1]; int fx=find(root[i],x),fy=find(root[i],y); if(fa[fx]==fa[fy]) puts("1"); else puts("0"); } } return 0; }
By NeighThorn
以上是关于BZOJ 3673: 可持久化并查集 by zky的主要内容,如果未能解决你的问题,请参考以下文章
BZOJ 3674可持久化并查集加强版&BZOJ 3673可持久化并查集 by zky 用可持久化线段树破之
[BZOJ3674]可持久化并查集加强版&[BZOJ3673]可持久化并查集 by zky
[bzoj3673][可持久化并查集 by zky] (rope(可持久化数组)+并查集=可持久化并查集)