论求 最有效的方法是
论求 最有效的方法是#
: 欧拉序 + 表
: 倍增
: 树链剖分
#include<bits/stdc++.h>
using namespace std;
const int N=5e5+5;
inline int read(){
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();}
while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return x*f;
}
int n,m,rt,cnt;
vector <int> G[N];
namespace standard_table{
int dfn[N],dep[N],f[N*2][21];
inline void dfs(int x,int fa){
dep[x]=dep[fa]+1;
dfn[x]=++cnt;
f[cnt][0]=x;
for(auto y:G[x]){
if(y==fa) continue;
dfs(y,x);
f[++cnt][0]=x;
}
}
inline int lca(int x,int y){
int l=dfn[x],r=dfn[y];
if(l>r) swap(l,r);
int k=log2(r-l+1);
if(dep[f[l][k]]<=dep[f[r-(1<<k)+1][k]]) return f[l][k];
return f[r-(1<<k)+1][k];
}
inline void pre_work(){
cnt=0;
dfs(rt,0);
for(int j=1;(1<<j)<=cnt;++j)
for(int i=1;i+(1<<j)-1<=cnt;++i)
f[i][j]=dep[f[i][j-1]]<dep[f[i+(1<<j-1)][j-1]]?
f[i][j-1]:f[i+(1<<j-1)][j-1];
}
inline void solve(){
pre_work();
while(m--){
int x=read(),y=read();
printf("%d\n",lca(x,y));
}
}
}
//standard_table:35 lines
//time:O(2nlogn+m)
//space:O(2nlogn)
namespace multiplication{
int dep[N],f[N][20];
inline void dfs(int x,int fa){
dep[x]=dep[fa]+1,f[x][0]=fa;
for(int i=1;i<=19;++i)
f[x][i]=f[f[x][i-1]][i-1];
for(auto y:G[x])
if(y!=fa) dfs(y,x);
}
inline int lca(int x,int y){
if(dep[x]<dep[y]) swap(x,y);
for(int i=19;i>=0;--i)
if(dep[f[x][i]]>=dep[y])
x=f[x][i];
if(x==y) return x;
for(int i=19;i>=0;--i)
if(f[x][i]!=f[y][i])
x=f[x][i],y=f[y][i];
return f[x][0];
}
inline void solve(){
dfs(rt,0);
while(m--){
int x=read(),y=read();
printf("%d\n",lca(x,y));
}
}
}
//multiplication:28 lines
//time:O((n+m)logn)
//space:O(nlogn)
namespace tree_chain_subdivision{
int dep[N],son[N],top[N],dfn[N],sz[N],f[N];
inline void dfs1(int x,int fa){
dep[x]=dep[fa]+1,sz[x]=1,f[x]=fa;
int maxson=-1;
for(auto y:G[x]){
if(y==fa) continue;
dfs1(y,x);
sz[x]+=sz[y];
if(maxson<sz[y]) son[x]=y,maxson=sz[y];
}
}
inline void dfs2(int x,int tp){
top[x]=tp,dfn[x]=++cnt;
if(!son[x]) return;
dfs2(son[x],tp);
for(auto y:G[x])
if(y!=f[x]&&y!=son[x])
dfs2(y,y);
}
inline int lca(int x,int y){
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]]) swap(x,y);
x=f[top[x]];
}
return dep[x]<dep[y]?x:y;
}
inline void solve(){
dfs1(rt,0);
dfs2(rt,rt);
while(m--){
int x=read(),y=read();
printf("%d\n",lca(x,y));
}
}
}
//tree_chain_subdivision:36 lines
//time:O(n+mlogn)
//space:O(n)
signed main(){
n=read(),m=read(),rt=read();
for(int i=1;i<n;++i){
int x=read(),y=read();
G[x].push_back(y);
G[y].push_back(x);
}
//standard_table::solve();
//multiplication::solve();
//tree_chain_subdivision::solve();
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现