1、题意:给一些点,有两种操作, 连通两个点和询问两个点最早是在什么时候连通
2、分析:这题用lct维护动态最小生成树就好。。但是过于暴力,我们可以倒着用并查集暴力查询,然后依旧是查询链上的最大值,然而这次我们不路径压缩,我们按秩合并,然后树高logn,接下来就随意弄啦
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
using namespace std;
#define M 1000010
inline int read(){
char ch = getchar(); int x = 0, f = 1;
while(ch < ‘0‘ || ch > ‘9‘){
if(ch == ‘-‘) f = -1;
ch = getchar();
}
while(‘0‘ <= ch && ch <= ‘9‘){
x = x * 10 + ch - ‘0‘;
ch = getchar();
}
return x * f;
}
int fa[M], Rank[M], dep[M], val[M];
inline int find(int x){
if(fa[x] == x) return x;
int ret = find(fa[x]);
dep[x] = dep[fa[x]] + 1;
return ret;
}
inline int lca(int x, int y){
int ans = 0;
while(x != y){
if(dep[x] < dep[y]) swap(x, y);
ans = max(ans, val[x]);
x = fa[x];
}
return ans;
}
int main(){
//freopen("0input.in", "r", stdin);
int n = read(), m = read();
for(int i = 1; i <= n; i ++){
fa[i] = i; Rank[i] = 1; dep[i] = 0;
}
int time = 0, ans = 0;
for(int i = 1; i <= m; i ++){
int op = read(), x = read(), y = read();
x ^= ans; y ^= ans;
if(!op){
int px = find(x), py = find(y);
time ++;
if(px != py){
if(Rank[px] >= Rank[py]){
fa[py] = px;
val[py] = time;
if(Rank[px] == Rank[py]) Rank[px] ++;
}
else{
fa[px] = py;
val[px] = time;
}
}
}
else{
int px = find(x), py = find(y);
if(px != py) ans = 0;
else ans = lca(x, y);
printf("%d\n", ans);
}
}
return 0;
}
?
时间: 2024-11-05 14:39:01