5883. 【NOIP2018模擬A組9.25】到不了(啟發式合併)
阿新 • • 發佈:2018-12-12
題目大意:
維護一個森林,支援連邊操作和查詢兩點 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); } } }