http://www.lydsy.com/JudgeOnline/problem.php?id=3674
http://www.lydsy.com/JudgeOnline/problem.php?id=3673
双倍经验啦啦啦。。
给主席树换了个名称果然高大上。。。
首先要可持久化并查集其实就是可持久化数组。。。
那么因为数组的形式是这样的$P[x]$,那么我们用一种数据结构实现查找x返回对应的$P[x]$即可啦啦啦。
然后那么我所学的可持久化目前只有主席树QAQ哪天去写写fhqtreap。。。
所以用主席树查找下标x,然后在叶子中维护父亲。
然后就完了
#include <cstdio> #include <cstring> #include <cmath> #include <string> #include <iostream> #include <algorithm> #include <queue> #include <set> #include <map> #include <ext/rope> using namespace std; typedef long long ll; #define rep(i, n) for(int i=0; i<(n); ++i) #define for1(i,a,n) for(int i=(a);i<=(n);++i) #define for2(i,a,n) for(int i=(a);i<(n);++i) #define for3(i,a,n) for(int i=(a);i>=(n);--i) #define for4(i,a,n) for(int i=(a);i>(n);--i) #define CC(i,a) memset(i,a,sizeof(i)) #define read(a) a=getint() #define print(a) printf("%d", a) #define dbg(x) cout << (#x) << " = " << (x) << endl #define error(x) (!(x)?puts("error"):0) #define rdm(x, i) for(int i=ihead[x]; i; i=e[i].next) inline const int getint() { int r=0, k=1; char c=getchar(); for(; c<'0'||c>'9'; c=getchar()) if(c=='-') k=-1; for(; c>='0'&&c<='9'; c=getchar()) r=r*10+c-'0'; return k*r; } const int N=2*1e5+10; struct node { int l, r, f; }t[N*100]; int cnt, root[N], n; void update(int l, int r, int &x, int pos, int f) { t[++cnt]=t[x]; x=cnt; if(l==r) { t[x].f=f; return; } int mid=(l+r)>>1; if(pos<=mid) update(l, mid, t[x].l, pos, f); else update(mid+1, r, t[x].r, pos, f); } int ask(int l, int r, int x, int pos) { if(l==r) return t[x].f; int mid=(l+r)>>1; if(pos<=mid) return ask(l, mid, t[x].l, pos); else return ask(mid+1, r, t[x].r, pos); } int P(int x, int y) { return ask(1, n, x, y); } int un(int &x, int a, int b) { update(1, n, x, a, b); return b; } // union p(a)=y int find(int &x, int y) { int f=P(x, y); return f==y?y:un(x, y, find(x, f)); } int main() { read(n); int m=getint(), la=0; for1(i, 1, n) update(1, n, root[0], i, i); for1(i, 1, m) { int c=getint(); root[i]=root[i-1]; if(c==1) { int x=getint(), y=getint(); x^=la; y^=la; int fx=find(root[i], x), fy=find(root[i], y); if(fx!=fy) un(root[i], fx, fy); } else if(c==2) root[i]=root[getint()^la]; else { int x=getint(), y=getint(); x^=la; y^=la; int fx=find(root[i], x), fy=find(root[i], y); printf("%d\n", la=(fx==fy)); } } return 0; }
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