//LCA //ST表 在线 #include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<cmath> #include<algorithm> #define maxn 500001 using namespace std; int n,m,cnt,root,head[maxn],depth[maxn]; int order[2*maxn],first[maxn];//order[x]dfs中第x次遍历的点(重复) first[x]记录点x在dfs中首次遍历顺序(不重复) int lg[2*maxn],f[2*maxn][21];//lg[x]记录log2x的向下取整值 f[x][k]表示包含x点共2^k个点中最小值 struct uio{ int next,to; }edge[2*maxn]; void add(int x,int y) { edge[++cnt].next=head[x]; edge[cnt].to=y; head[x]=cnt; } void dfs(int x,int pre)//pre为上次遍历过节点 防止走重 { order[++cnt]=x; first[x]=cnt; for(int i=head[x];i!=-1;i=edge[i].next) { int u=edge[i].to; if(u!=pre) { depth[u]=depth[x]+1; dfs(u,x); order[++cnt]=x; } } } void ST() { for(int i=1;i<=cnt;i++) f[i][0]=order[i]; lg[1]=0,lg[2]=1; for(int i=3;i<=cnt;i++) { lg[i]=lg[i-1]; if(1<<lg[i-1]+1==i) lg[i]++; } int num=lg[cnt]; for(int j=1;j<=num;j++) for(int i=1;i+(1<<j)-1<=cnt;i++)// i+(1<<j)-1 -1原因:区间包括自身 { if(depth[f[i][j-1]]<depth[f[i+(1<<j-1)][j-1]]) f[i][j]=f[i][j-1]; else f[i][j]=f[i+(1<<j-1)][j-1]; } } int RMQ(int l,int r) { int k=lg[r-l+1]; if(depth[f[l][k]]<depth[f[r-(1<<k)+1][k]])//r-(1<<k)+1 +1原因:区间包括自身 return f[l][k]; else return f[r-(1<<k)+1][k];//此处+1原因同上 } int ask(int x,int y) { x=first[x]; y=first[y]; if(x>y) swap(x,y); return RMQ(x,y); } int main() { scanf("%d%d%d",&n,&m,&root); memset(head,-1,sizeof(head)); for(int i=1;i<=n-1;i++) { int u,v; scanf("%d%d",&u,&v); add(u,v); add(v,u); } cnt=0; dfs(root,-1); ST(); for(int i=1;i<=m;i++) { int u,v; scanf("%d %d",&u,&v); printf("%d\n",ask(u,v)); } return 0; }
LCA ST表
猜你喜欢
转载自www.cnblogs.com/water-radish/p/9280507.html
今日推荐
周排行