[BZOJ3674]可持久化并查集加强版
试题描述
自从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
输入
见“试题描述”
输出
见“试题描述”
输入示例
5 6 1 1 2 3 1 2 2 1 3 0 3 2 1 3 1 2
输出示例
1 0 1
数据规模及约定
见“试题描述”
题解
同上一题,记得改数据范围和强制在线。
#include <iostream> #include <cstdio> #include <algorithm> #include <cmath> #include <stack> #include <vector> #include <queue> #include <cstring> #include <string> #include <map> #include <set> using namespace std; const int BufferSize = 1 << 16; char buffer[BufferSize], *Head, *Tail; inline char Getchar() { if(Head == Tail) { int l = fread(buffer, 1, BufferSize, stdin); Tail = (Head = buffer) + l; } return *Head++; } int read() { int x = 0, f = 1; char c = Getchar(); while(!isdigit(c)){ if(c == '-') f = -1; c = Getchar(); } while(isdigit(c)){ x = x * 10 + c - '0'; c = Getchar(); } return x * f; } #define maxn 200010 #define maxnode 14400000 int ToT, fa[maxnode], siz[maxnode], lc[maxnode], rc[maxnode]; void updatefa(int& y, int x, int l, int r, int p, int Fa) { fa[y = ++ToT] = fa[x]; siz[y] = siz[x]; if(l == r){ fa[y] = Fa; return ; } int mid = l + r >> 1; lc[y] = lc[x]; rc[y] = rc[x]; if(p <= mid) updatefa(lc[y], lc[x], l, mid, p, Fa); else updatefa(rc[y], rc[x], mid+1, r, p, Fa); return ; } void updatesiz(int& y, int x, int l, int r, int p, int Siz) { fa[y = ++ToT] = fa[x]; siz[y] = siz[x]; if(l == r){ siz[y] = Siz; return ; } int mid = l + r >> 1; lc[y] = lc[x]; rc[y] = rc[x]; if(p <= mid) updatesiz(lc[y], lc[x], l, mid, p, Siz); else updatesiz(rc[y], rc[x], mid+1, r, p, Siz); } int qfa(int o, int l, int r, int p) { if(!o) return 0; if(l == r) return fa[o]; int mid = l + r >> 1; if(p <= mid) return qfa(lc[o], l, mid, p); return qfa(rc[o], mid+1, r, p); } int qsiz(int o, int l, int r, int p) { if(!o) return 0; if(l == r) return siz[o]; int mid = l + r >> 1; if(p <= mid) return qsiz(lc[o], l, mid, p); return qsiz(rc[o], mid+1, r, p); } int n, rt[maxn]; int findset(int o, int x) { int tfa = qfa(o, 1, n, x); return tfa == x ? x : findset(o, tfa); } int main() { // freopen("data.in", "r", stdin); n = read(); int q = read(); for(int i = 1; i <= n; i++) updatefa(rt[0], rt[0], 1, n, i, i), updatesiz(rt[0], rt[0], 1, n, i, 1); bool lst = 0; for(int i = 1; i <= q; i++) { int tp = read(); if(tp == 1) { int a = findset(rt[i-1], read() ^ lst), b = findset(rt[i-1], read() ^ lst); if(a == b){ rt[i] = rt[i-1]; continue; } int sa = qsiz(rt[i-1], 1, n, a), sb = qsiz(rt[i-1], 1, n, b); if(sa < sb) swap(a, b), swap(sa, sb); updatefa(rt[i], rt[i-1], 1, n, b, a); updatesiz(rt[i], rt[i], 1, n, a, sa + sb); } if(tp == 2) { int k = read() ^ lst; rt[i] = rt[k]; } if(tp == 3) { int a = findset(rt[i-1], read() ^ lst), b = findset(rt[i-1], read() ^ lst); // printf("%d %d ", a, b); lst = a == b; printf("%d ", lst); rt[i] = rt[i-1]; } // printf("ToT: %d ", ToT); } return 0; }