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

Sample Output

1
0
1

HINT

 

Source

你可能感兴趣的:(并查集)