bzoj3674 可持久化并查集加强版
Posted wfj_2048
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj3674 可持久化并查集加强版相关的知识,希望对你有一定的参考价值。
Description
自从zkysb出了可持久化并查集后……
hzwer:乱写能AC,暴力踩标程
KuribohG:我不路径压缩就过了!
ndsf:暴力就可以轻松虐!
zky:……
n个集合 m个操作
操作:
1 a b 合并a,b所在集合
2 k 回到第k次操作之后的状态(查询算作操作)
3 a b 询问a,b是否属于同一集合,是则输出1否则输出0
请注意本题采用强制在线,所给的a,b,k均经过加密,加密方法为x = x xor lastans,lastans的初始值为0
0<n,m<=2*10^5
Sample Input
5 6
1 1 2
3 1 2
2 1
3 0 3
2 1
3 1 2
1 1 2
3 1 2
2 1
3 0 3
2 1
3 1 2
Sample Output
1
0
1
0
1
正解:可持久化线段树+启发式合并。
原来可持久化数组就是用可持久化线段树维护。。那么我们每次合并时,直接将秩小的合并到秩大的树上面,注意秩相等的时候秩要加1。询问的话就直接在线段树里找当前点的根,撤回的话直接把当前时间的根赋值成历史时间的根就行了。
其实我只AC了加强版,普通版怎么也AC不了。。有人帮我查一下错吗qwq。。
1 //It is made by wfj_2048~ 2 #include <algorithm> 3 #include <iostream> 4 #include <cstring> 5 #include <cstdlib> 6 #include <cstdio> 7 #include <vector> 8 #include <cmath> 9 #include <queue> 10 #include <stack> 11 #include <map> 12 #include <set> 13 #define inf (1<<30) 14 #define N (200010) 15 #define il inline 16 #define RG register 17 #define ll long long 18 19 using namespace std; 20 21 int sum[80*N],dep[80*N],ls[80*N],rs[80*N],rt[N],n,m,sz,ans; 22 23 il int gi(){ 24 RG int x=0,q=1; RG char ch=getchar(); while ((ch<‘0‘ || ch>‘9‘) && ch!=‘-‘) ch=getchar(); 25 if (ch==‘-‘) q=-1,ch=getchar(); while (ch>=‘0‘ && ch<=‘9‘) x=x*10+ch-48,ch=getchar(); return q*x; 26 } 27 28 il void build(RG int &x,RG int l,RG int r){ 29 x=++sz; if (l==r){ sum[x]=l,dep[x]=1; return; } 30 RG int mid=(l+r)>>1; build(ls[x],l,mid),build(rs[x],mid+1,r); return; 31 } 32 33 il void add(RG int x,RG int &y,RG int l,RG int r,RG int u){ //dep+1 34 y=++sz; if (l==r){ sum[y]=u,dep[y]=dep[x]+1; return; } 35 ls[y]=ls[x],rs[y]=rs[x]; RG int mid=(l+r)>>1; 36 u<=mid ? add(ls[x],ls[y],l,mid,u) : add(rs[x],rs[y],mid+1,r,u); return; 37 } 38 39 il void merge(RG int x,RG int &y,RG int l,RG int r,RG int u,RG int fa){ //按秩合并 40 y=++sz; if (l==r){ sum[y]=fa,dep[y]=dep[x]; return; } 41 ls[y]=ls[x],rs[y]=rs[x]; RG int mid=(l+r)>>1; 42 u<=mid ? merge(ls[x],ls[y],l,mid,u,fa) : merge(rs[x],rs[y],mid+1,r,u,fa); return; 43 } 44 45 il int query(RG int x,RG int l,RG int r,RG int u){ //查询当前结点的编号 46 if (l==r) return x; RG int mid=(l+r)>>1; 47 return u<=mid ? query(ls[x],l,mid,u) : query(rs[x],mid+1,r,u); 48 } 49 50 il int find(RG int rt,RG int u){ RG int y=query(rt,1,n,u); return sum[y]==u ? y : find(rt,sum[y]); } //找根 51 52 il void work(){ 53 n=gi(),m=gi(); RG int x,y,type; build(rt[0],1,n); 54 for (RG int i=1;i<=m;++i){ 55 type=gi(),rt[i]=rt[i-1]; 56 if (type==1){ 57 x=gi()^ans,y=gi()^ans; 58 x=find(rt[i],x),y=find(rt[i],y); 59 if (dep[x]>dep[y]) swap(x,y); 60 merge(rt[i-1],rt[i],1,n,sum[x],sum[y]); 61 if (dep[x]==dep[y]) add(rt[i],rt[i],1,n,sum[y]); 62 } else if (type==2) x=gi()^ans,rt[i]=rt[x]; else{ 63 x=gi()^ans,y=gi()^ans; 64 ans=sum[find(rt[i],x)]==sum[find(rt[i],y)]; 65 printf("%d\n",ans); 66 } 67 } 68 return; 69 } 70 71 int main(){ 72 work(); 73 return 0; 74 }
以上是关于bzoj3674 可持久化并查集加强版的主要内容,如果未能解决你的问题,请参考以下文章