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
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