BZOJ3674: 可持久化并查集加强版
题解:我们选择用一颗可持久化线段树维护来维护叶子节点的父亲 通过复杂度证明 我们可以知道按秩合并可以将查询根的时间保障在logn的范围内(因为按秩合并的实质是启发式合并 我们可以把深度作为启发量 进行合并保证合并次数只有logn次 从而查询根的复杂度只有logn) 既然和我们可以在logn的复杂度下查找到根 那我们通过可持久线段树维护以后可以在2个log的情况下查询这个点在当前版本内的集合中的根 然后我们就可以维护可持久化并查集 也能返回到其任何历史版本中
/************************************************************** Problem: 3674 User: c20161007 Language: C++ Result: Accepted Time:1124 ms Memory:80204 kb ****************************************************************/ #include <bits/stdc++.h> const int MAXN=2e5+10; using namespace std; int n,m,cnt,rt[MAXN],fa,dep,cnt1,k,a,b,op,dep1,dep2,last; typedef struct node{ int l,r,f,dep; }node; node d[MAXN*25]; int read(){ int x=0,f=1;char ch=getchar(); while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();} while(isdigit(ch))x=x*10+ch-'0',ch=getchar(); return f*x; } void built(int &x,int l,int r){ if(!x)x=++cnt; if(l==r){d[x].f=l,d[x].dep=1;return ;} int mid=(l+r)>>1; built(d[x].l,l,mid); built(d[x].r,mid+1,r); } void update(int &x,int y,int l,int r,int t){ x=++cnt;d[x]=d[y]; if(l==r){d[x].f=fa;d[x].dep=dep;return ;} int mid=(l+r)>>1; if(t<=mid)update(d[x].l,d[y].l,l,mid,t); else update(d[x].r,d[y].r,mid+1,r,t); } int find1(int x,int l,int r,int t){ if(l==r)return x; int mid=(l+r)>>1; if(t<=mid)return find1(d[x].l,l,mid,t); else return find1(d[x].r,mid+1,r,t); } int _find(int x,int num){ while(1){ int _t=find1(rt[num],1,n,x); if(d[_t].f==x)return _t; x=d[_t].f; } } int res; int main(){ n=read();m=read();built(rt[0],1,n);res=0; for(int i=1;i<=m;i++){ op=read(); if(op==1){ a=read();b=read();rt[i]=rt[i-1]; a=a^res;b=b^res; a=_find(a,i);dep1=d[a].dep; b=_find(b,i);dep2=d[b].dep; if(a==b)continue; if(dep1>dep2)fa=d[a].f,dep=0,update(rt[i],rt[i],1,n,d[b].f); else if(dep1<dep2)fa=d[b].f,dep=0,update(rt[i],rt[i],1,n,d[a].f); else fa=d[a].f,dep=0,update(rt[i],rt[i],1,n,d[b].f),fa=d[a].f,dep=dep1+1,update(rt[i],rt[i],1,n,d[a].f); } else if(op==2)k=read(),k=res^k,rt[i]=rt[k]; else{ a=read();b=read();a=res^a;b=res^b; rt[i]=rt[i-1]; a=_find(a,i); b=_find(b,i); if(a==b)res=1; else res=0; printf("%d\n",res); } } return 0; }
3674: 可持久化并查集加强版
Time Limit: 15 Sec Memory Limit: 256 MBSubmit: 5025 Solved: 1887
[Submit][Status][Discuss]
Description
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
Input
Output
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