因为NOI2018D1T1似乎还有可持久化并查集解法 所以去学了一学
调了我好久 结果是数组开小了
n
n
和 不同阶的出题人都是耍流氓!!!
好现在步入正题 我们对于并查集实际上维护的是一个可以单点修改和查询的数组
如果要支持可持久化的话 我们可以考虑用可持久化线段树来维护这个数组
因为每次修改不超过
log(n)
l
o
g
(
n
)
个节点 那么我们就可以对于并查集按照启发式合并
时间复杂度
O(Mlog2n)
O
(
M
l
o
g
2
n
)
空间复杂度
O(Mlogn)
O
(
M
l
o
g
n
)
然后再讲下启发式合并 在两个并查集合并的过程中 每次我们把子树深度小的往子树深度大的集合中合并 那么可以证明复杂度是
O(logn)
O
(
l
o
g
n
)
级别的 那么就可以不用路径压缩失去一些信息了
/**************************************************************
Problem: 3674
User: lunch
Language: C++
Result: Accepted
Time:1340 ms
Memory:189584 kb
****************************************************************/
#include<bits/stdc++.h>
#define For(i, a, b) for(register int i = a; i <= b; ++ i)
using namespace std;
const int maxn = 2e5 + 10;
int root[maxn], n, m, now, lastans;
namespace Chairman_Tree
{
#define ls(x) (T[x].ch[0])
#define rs(x) (T[x].ch[1])
#define mid ((l + r) >> 1)
int cnt;
struct node
{
int ch[2], fa, height;
}T[maxn * 60];
void build(int &x, int l, int r)
{
x = ++ cnt;
if(l == r)
T[x].fa = l;
else
{
build(ls(x), l, mid);
build(rs(x), mid + 1, r);
}
}
int query(int x, int l, int r, int p)
{
if(l == r)
return x;
if(p <= mid)
return query(ls(x), l, mid, p);
return query(rs(x), mid + 1, r, p);
}
void update(int &x, int pre, int l, int r, int p, int dad)
{
T[x = ++ cnt] = T[pre];
if(l == r)
T[x].fa = dad;
else
{
if(p <= mid)
update(ls(x), ls(pre), l, mid, p, dad);
else
update(rs(x), rs(pre), mid + 1, r, p, dad);
}
}
void add(int &x, int pre, int l, int r, int p)
{
T[x = ++ cnt] = T[pre];
if(l == r)
++ T[x].height;
else
{
if(p <= mid)
add(ls(x), ls(pre), l, mid, p);
else
add(rs(x), rs(pre), mid + 1, r, p);
}
}
int find(int x)
{
int dad = query(now, 1, n, x);
while(T[dad].fa != x)
{
x = T[dad].fa;
dad = query(now, 1, n, x);
}
return dad;
}
}
using namespace Chairman_Tree;
int main()
{
#ifndef ONLINE_JUDGE
freopen("3674.in", "r", stdin);
freopen("3674.out", "w", stdout);
#endif
int x, y, z;
scanf("%d%d", &n, &m);
build(root[0], 1, n);
now = root[0];
For(i, 1, m)
{
scanf("%d%d", &x, &y);
y ^= lastans;
if(x == 2)
now = root[y];
else
scanf("%d", &z);
z ^= lastans;
if(x == 1)
{
int u = find(y), v = find(z);
if(T[u].fa != T[v].fa)
{
if(T[u].height > T[v].height)
update(now, now, 1, n, T[v].fa, T[u].fa);
else
{
update(now, now, 1, n, T[u].fa, T[v].fa);
if(T[u].height == T[v].height)
add(now, now, 1, n, T[v].fa);
}
}
}
if(x == 3)
printf("%d\n", lastans = (T[find(y)].fa == T[find(z)].fa ? 1 : 0));
root[i] = now;
}
return 0;
}