模板 树上求LCA 倍增和树链剖分
//233
模板 LCA
void dfs(int x,int f){
for(int i=0;i<E[x].size();i++){
int v = E[x][i];
if(v==f)continue;
deep[v]=deep[x]+1;
lca[v][0]=x;
for(int j=1;j<maxm;j++){
int fa = lca[v][j-1];
if(fa==0)continue;
lca[v][j]=lca[fa][j-1];
}
dfs(v,x);
}
}
int up(int x,int d)
{
for(int i=maxm-1;i>=0;i--)
{
if(d<(1<<i))continue;
x=lca[x][i];
d-=(1<<i);
}
return x;
}
int Lca(int x,int y)
{
if(deep[x]>deep[y])swap(x,y);
y=up(y,deep[y]-deep[x]);
if(x==y)return x;
for(int i=maxm-1;i>=0;i--)
{
if(lca[x][i]!=lca[y][i])
x=lca[x][i],y=lca[y][i];
}
return lca[x][0];
}
//树链剖分
#include <cstdio>
#include <cstdlib>
#define maxm 200010
struct edge{int to,len,next;}E[maxm];
int cnt,last[maxm],fa[maxm],top[maxm],deep[maxm],siz[maxm],son[maxm],val[maxm];
void addedge(int a,int b,int len=0)
{
E[++cnt]=(edge){b,len,last[a]},last[a]=cnt;
}
void dfs1(int x)
{
deep[x]=deep[fa[x]]+1;siz[x]=1;
for(int i=last[x];i;i=E[i].next)
{
int to=E[i].to;
if(fa[x]!=to&&!fa[to]){
val[to]=E[i].len;
fa[to]=x;
dfs1(to);
siz[x]+=siz[to];
if(siz[son[x]]<siz[to])son[x]=to;
}
}
}
void dfs2(int x)
{
if(x==son[fa[x]])top[x]=top[fa[x]];
else top[x]=x;
for(int i=last[x];i;i=E[i].next)if(fa[E[i].to]==x)dfs2(E[i].to);
}
void init(int root){dfs1(root),dfs2(root);}
int query(int x,int y)
{
for(;top[x]!=top[y];deep[top[x]]>deep[top[y]]?x=fa[top[x]]:y=fa[top[y]]);
return deep[x]<deep[y]?x:y;
}
int n,m,x,y,v;
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<n;i++)
{
scanf("%d%d",&x,&y);addedge(x,y,v);addedge(y,x,v);
}
init(1);
for(int i=1;i<=m;i++)
{
scanf("%d%d",&x,&y);
printf("%d\n",query(x,y));
}
return 0 ;
}