【BZOJ】3673: 可持久化并查集 by zky & 3674: 可持久化并查集加强版(可持久化线段树)

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

Sample Output

1
0
1

HINT

 

Source

原文地址:https://www.cnblogs.com/iwtwiioi/p/4151710.html