可持久化并查集
\mathbf{可持久化并查集}
可持久化并查集
题目读完显然就是并查集,但是要维护每个点到根的距离
题目读完显然就是并查集,但是要维护每个点到根的距离
题目读完显然就是并查集,但是要维护每个点到根的距离
如果不用路径压缩的话很简单,每次寻找父节点的时候把整个树的深度都更新一遍
如果不用路径压缩的话很简单,每次寻找父节点的时候把整个树的深度都更新一遍
如果不用路径压缩的话很简单,每次寻找父节点的时候把整个树的深度都更新一遍
但是要注意
M
X
Y
并不是把
X
接在
Y
后面,而是把
X
所在的一列整体接在
Y
一列的后面
但是要注意\mathrm{M\quad X\quad Y}并不是把\mathrm{X}接在\mathrm{Y}后面,而是把\mathrm{X}所在的一列整体接在\mathrm{Y}一列的后面
但是要注意MXY并不是把X接在Y后面,而是把X所在的一列整体接在Y一列的后面
可以注意到数据范围如果不用路径压缩会超时,显然要进行路径压缩,但是路径压缩的时候要维护节点的深度
可以注意到数据范围如果不用路径压缩会超时,显然要进行路径压缩,但是路径压缩的时候要维护节点的深度
可以注意到数据范围如果不用路径压缩会超时,显然要进行路径压缩,但是路径压缩的时候要维护节点的深度
这里使用两个数组来维护
d
e
e
p
维护某个节点的深度,
s
e
t
t
维护某个节点所在队列的舰艇个数
这里使用两个数组来维护\mathrm{deep}维护某个节点的深度,\mathrm{sett}维护某个节点所在队列的舰艇个数
这里使用两个数组来维护deep维护某个节点的深度,sett维护某个节点所在队列的舰艇个数
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
const int MAXN = 30005;
int f[MAXN];
int deep[MAXN];
int sett[MAXN];
int getfather(int k){
if(f[k] == k) return k;
int p = f[k];
f[k] = getfather(f[k]);
deep[k] += deep[p];
sett[k] = sett[f[k]];
return f[k];
}
int main(){
for(int i = 1; i <= 30000; i ++){
f[i] = i;
deep[i] = 0;
sett[i] = 1;
}
int T;
cin>>T;
for(int i = 1; i <= T; i ++){
char s;
int x,y,fa,fb;
cin>>s>>x>>y;
if(s == 'M'){
fa = getfather(x);
fb = getfather(y);
f[fa] = fb;
deep[fa] += sett[fb];
sett[fa] += sett[fb];
sett[fb] = sett[fa];
}
if(s == 'C'){
int fa = getfather(x);
int fb = getfather(y);
if(fa == fb) cout<<abs(deep[x] - deep[y]) - 1<<endl;
else cout<<-1<<endl;
}
}
return 0;
}