分析:多节点的LCA就是dfs序中最大最小两个节点的LCA。所以只要每次维持给出节点的dfs序的最大最小,然后就是两点的LCA
代码:
rmq的st+lca的倍增
#include<stdio.h> #include<iostream> #include<algorithm> #include<string.h> #include<math.h> //#include<bits/stdc++.h> using namespace std; const int max_=311111; int n; int edge[max_*2]; bool vis[max_]; int deep[max_]; int p[max_][25]; int dp_min[max_][25]; int dp_max[max_][25]; int a[max_]; //int smax[max_][25],smin[max_][23]; int tot,idx; void init() { tot=0; memset(edge,-1,sizeof(edge)); idx=0; memset(vis,0,sizeof(vis)); memset(deep,0,sizeof(deep)); memset(p,-1,sizeof(p)); } struct tree{ int to; int next; }G[max_*2]; void add_edge(int u,int v) { G[++tot].to=v; G[tot].next=edge[u]; edge[u]=tot; } void dfs(int u) { vis[u]=1; a[u-1]=idx++; for(int i=edge[u];~i;i=G[i].next) { int v=G[i].to; if(!vis[v]) { p[v][0]=u; deep[v]=deep[u]+1; dfs(v); } } } int Max(int x,int y) { if(a[x]>a[y]) return x; else return y; } int Min(int x,int y) { if(a[x]>a[y]) return y; else return x; } void st_init() { for(int i=0;i<n;i++) { dp_max[i][0]=i, dp_min[i][0]=i; } for(int j=1;(1<<j)<=n;j++) for(int i=0;i+(1<<j)-1<n;i++) { dp_max[i][j]=Max(dp_max[i][j-1],dp_max[i+(1<<(j-1))][j-1]); dp_min[i][j]=Min(dp_min[i][j-1],dp_min[i+(1<<(j-1))][j-1]); } } int st_q_max(int l,int r) { int k=0; while((1<<(k+1))<=r-l+1) k++; return Max(dp_max[l][k],dp_max[r-(1<<k)+1][k]); } int st_q_min(int l,int r) { int k=0; while((1<<(k+1))<=r-l+1) k++; return Min(dp_min[l][k],dp_min[r-(1<<k)+1][k]); } void lca_init() { for(int j=1;(1<<j)<=n;j++) for(int i=1;i<=n;i++) if(~p[i][j-1]) p[i][j]=p[p[i][j-1]][j-1]; } int lca(int u,int v) { if(deep[u]<deep[v])//u_max; swap(u,v); int k=deep[u]-deep[v]; for(int i=0;(1<<i)<=k;i++) { if((1<<i)&k) u=p[u][i]; } if(u==v) return u; int N=log2((double)n); for(int i=N;i>=0;i--) { if(p[u][i]!=p[v][i]) { u=p[u][i], v=p[v][i]; } } return p[u][0]; } int main() { while(~scanf("%d",&n)){ init(); int u,v; for(int i=1;i<n;i++) { scanf("%d %d",&u,&v); add_edge(u,v); add_edge(v,u); } dfs(1); st_init(); int Q; scanf("%d",&Q); lca_init(); while(Q--) { int l,r; scanf("%d %d",&l,&r); l--,r--; int id_max=st_q_max(l,r)+1; int id_min=st_q_min(l,r)+1; printf("%d ",lca(id_max,id_min)); } } }