思路
说是可持久化并查集,实际上就是把并查集使用的数组变成可持久化数组.
当然,可持久化并查集路径压缩不现实,这样可能总共需要修改个值,空间复杂度可能不好过去.
想象当初学并查集时使用的优化,出了路径压缩,还有按秩合并.这样一次只需要修改个值,而且复杂度基本一样.
这样子时间复杂度为,空间复杂度为
.
代码
#include<bits/stdc++.h> using namespace std; #define MAXN 200005 int N, M; int f[MAXN], s[MAXN]; int T[MAXN], L[MAXN * 80], R[MAXN * 80], v_f[MAXN * 80], v_s[MAXN * 80], tot; int X(MAXN * 80 - 1); int Modify( int pre, int c, int l, int r, int x ){ if ( l == r ) return v_f[c] = v_f[pre], v_s[c] = v_s[pre], c; int mid((l + r) >> 1); if ( x <= mid ) return R[c] = R[pre], Modify( L[pre], L[c] = ++tot, l, mid, x ); return L[c] = L[pre], Modify( R[pre], R[c] = ++tot, mid + 1, r, x ); } int Get( int c, int l, int r, int x ){ if ( l == r ) return c; int mid( ( l + r ) >> 1); if ( x <= mid ) return Get( L[c], l, mid, x ); return Get( R[c], mid + 1, r, x ); } int find( int c, int x ){ int fa(v_f[Get( c, 1, N, x )]); return fa == x ? x : find( c, fa ); } void Merge( int pre, int c, int x, int y ){ int sx(v_s[Get( pre, 1, N, x )]), sy(v_s[Get( pre, 1, N, y )]); if ( sx > sy ) swap( x, y ), swap( sx, sy ); L[X] = R[X] = 0; v_f[Modify( pre, X, 1, N, x )] = y; v_s[Modify( X, c, 1, N, y )] = sx + sy; } void Build( int c, int l, int r ){ if ( l == r ){ v_f[c] = f[l], v_s[c] = s[l]; return; } int mid((l + r) >> 1); Build( L[c] = ++tot, l, mid ); Build( R[c] = ++tot, mid + 1, r ); } int main(){ scanf( "%d%d", &N, &M ); for ( int i = 1; i <= N; ++i ) f[i] = i, s[i] = 1; Build( T[0] = ++tot, 1, N ); int last_ans(0); for ( int i = 1; i <= M; ++i ){ int op, x, y; scanf( "%d%d", &op, &x ); if ( op == 1 ){ scanf( "%d", &y ); x = find( T[i - 1], x ^ last_ans ); y = find( T[i - 1], y ^ last_ans ); if ( x == y ){ T[i] = T[i - 1]; continue; } Merge( T[i - 1], T[i] = ++tot, x, y ); } if ( op == 2 ) T[i] = T[x ^ last_ans]; if ( op == 3 ) scanf( "%d", &y ), T[i] = T[i - 1], printf( find( T[i], x ^ last_ans ) == find( T[i], y ^ last_ans ) ? "1\n" : "0\n" ); } return 0; }