bzoj 3674: 可持久化并查集加强版 (启发式合并+主席树)
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
思路;
就是bzoj 3673数据范围加大了下。。卡了下其他写法,启发式合并+主席树的写法不会被卡。。
启发式合并也就是按秩合并,把小的并到大的。主席树里多维护一个数组dep,表示集合秩的大小。
又水一道,美滋滋
#include<bits/stdc++.h> using namespace std; #define mid int m = (l + r) >> 1 const int M = 5e6 + 10; const int Max = 2e5+10; int sum[M],ls[M],rs[M],dep[M],n,idx,root[Max]; void build(int l,int r,int &rt){ rt = ++idx; if(l == r){ sum[rt] = l; return ; } mid; build(l,m,ls[rt]); build(m+1,r,rs[rt]); return ; } void update(int old,int &rt,int p,int c,int l,int r){ rt = ++idx; ls[rt] = ls[old]; rs[rt] = rs[old]; dep[rt] = dep[old]; if(l == r){ sum[rt] = c; return ; } mid; if(p <= m) update(ls[old],ls[rt],p,c,l,m); else update(rs[old],rs[rt],p,c,m+1,r); } int query(int p,int l,int r,int rt){ if(l == r) return rt; mid; if(p <= m) return query(p,l,m,ls[rt]); else return query(p,m+1,r,rs[rt]); } void add(int p,int l,int r,int rt){ if(l == r){ dep[rt] ++; return; } mid; if(p <= m) add(p,l,m,ls[rt]); else add(p,m+1,r,rs[rt]); } int fd(int x,int rt){ int pos = query(x,1,n,rt); if(x == sum[pos]) return pos; return fd(sum[pos],rt); } int main() { int q,op,x,y,k; scanf("%d%d",&n,&q); build(1,n,root[0]); for(int i = 1;i <= q;i ++){ scanf("%d",&op); if(op == 1){ scanf("%d%d",&x,&y); root[i] = root[i-1]; int fx = fd(x,root[i-1]); int fy = fd(y,root[i-1]); if(sum[fx] == sum[fy]) continue; if(dep[fx] > dep[fy]) swap(fx,fy); update(root[i-1],root[i],sum[fx],sum[fy],1,n); if(dep[fx] == dep[fy]) add(sum[fy],1,n,root[i]); } else if(op == 2){ scanf("%d",&k); root[i] = root[k]; } else { root[i] = root[i-1]; scanf("%d%d",&x,&y); int fx = fd(x,root[i]); int fy = fd(y,root[i]); if(sum[fx] == sum[fy]) printf("1\n"); else printf("0\n"); } } return 0; }