题目大意:
维护一个森林,支持连边操作和查询两点 LCA 操作
思路:
启发式合并,每次把小的树连接到大的树上面就好了,暴力重构lca数组,维护个根,就可以快速得出lca了
还可以离线lct,这个我不是很懂…晚上可以问问dalao们
程序:
#include<cstdio>
#include<iostream>
#include<algorithm>
#define N 100005
using namespace std;
int cnt,n,m,u,v,op,q;
int size[N],f[N][21],last[N],dep[N],rt[N],root1[N];
struct tree{int to,next;}e[N*2];
void add(int x,int y){
e[++cnt].to=y; e[cnt].next=last[x]; last[x]=cnt;
e[++cnt].to=x; e[cnt].next=last[y]; last[y]=cnt;
}
void dfs(int x,int fa){
f[x][0]=fa;
for (int i=last[x];i;i=e[i].next)
if (e[i].to!=fa){
dep[e[i].to]=dep[x]+1;
dfs(e[i].to,x);
size[x]+=size[e[i].to];
}
}
int root(int x){
for (int i=20;i>=0;i--) if (f[x][i]) x=f[x][i];
return x;
}
void make(int x,int fa){
for (int i=1;i<=20;i++) f[x][i]=f[f[x][i-1]][i-1];
for (int i=last[x];i;i=e[i].next)
if (e[i].to!=fa){
dep[e[i].to]=dep[x]+1;
f[e[i].to][0]=x;
make(e[i].to,x);
}
}
int lca(int x,int y){
if (dep[x]>dep[y]) swap(x,y);
for (int i=20;i>=0;i--)
if (dep[f[y][i]]>=dep[x]) y=f[y][i];
if (x==y) return x;
for (int i=20;i>=0;i--)
if (f[y][i]!=f[x][i]) y=f[y][i],x=f[x][i];
return f[x][0];
}
int main(){
freopen("arrival.in","r",stdin);
freopen("arrival.out","w",stdout);
scanf("%d%d",&n,&m);
for (int i=1;i<=m;i++) scanf("%d",&rt[i]);
for (int i=1;i<=n-m;i++){
scanf("%d%d",&u,&v);
add(u,v);
}
for (int i=1;i<=n;i++) size[i]=1;
for (int i=1;i<=m;i++) {
dep[rt[i]]=1;
dfs(rt[i],0);
}
for (int j=1;j<=20;j++)
for (int i=1;i<=n;i++)
f[i][j]=f[f[i][j-1]][j-1];
for (int i=1;i<=n;i++){
int o=root(i);
if (o) root1[i]=o;
else root1[i]=i;
}
scanf("%d",&q);
for (int i=1;i<=q;i++){
scanf("%d%d%d",&op,&u,&v);
if (op==1){
int x=root(u),y=root(v);
if (x==y) continue;
if (size[x]>size[y]) {
f[v][0]=u;
size[x]+=size[y];
dep[v]=dep[u]+1;
root1[x]=root1[x];
add(u,v);
make(v,u);
} else {
f[u][0]=v;
size[y]+=size[x];
dep[u]=dep[v]+1;
root1[y]=root1[x];
add(u,v);
make(u,v);
}
} else {
if (root(u)!=root(v)){
printf("orzorz\n");
continue;
}
int x=root(u);
int o=lca(u,v),t=lca(root1[x],v);
if (dep[o]<dep[t]) o=t;
t=lca(root1[x],u);
if (dep[o]<dep[t]) o=t;
printf("%d\n",o);
}
}
}