st表 LCA
我当时知道ST表可以 求 LCA 的时候是极为震惊的,可以在需要反复使用 LCA 的时候卡常使用。
ST表!用于解决 RMQ问题
怎么实现?
考虑把求 LCA 转换为 RMQ问题。我们对于树求一遍欧拉序,就是那个回溯也会记录的那个。我们处理出每个数第一次在欧拉序中出现的位置,欧拉序上每个位置的深度,以及欧拉序上每个位置出现的点的编号。这些信息都可以在一次 中求出。然后不难发现在回溯过程中加入的点是之前遍历的点的祖先,由此也不难推出结论。
在两个点在欧拉序上第一次出现的位置的区间中间的深度最小的点就是这两个点的 LCA
那么直接变成 RMQ问题,上 ST表。
Code:
int idx;
int dfn[N + 3], app[2 * N + 3], dep2[2 * N + 3];
int dep[N + 3];
void dfs1(int u, int f, int deep){
dfn[u] = ++idx;
app[idx] = u;
dep[u] = deep;
dep2[idx] = deep;
for(int i = head[u]; ~i; i = nxt[i]){
int v = to[i];
if(v == f) continue;
dfs1(v, u, deep + 1);
app[++idx] = u;
dep2[idx] = deep;
}
}
int lg2[2 * N + 3];
int st[N * 2 + 3][LG + 4];
void init_ST(){
for(int i = 1; i <= (n << 1); ++i){
st[i][0] = i;
}
lg2[1]=0;
for(int i = 2; i <= (n << 1); ++i){
lg2[i] = lg2[i >> 1] + 1;
}
for(int j = 1; (1 << j) <= (n << 1); ++j){
for(int i = 1; i + (1 << j) - 1 <= (n << 1); ++i){
int a = st[i][j - 1], b = st[i + (1 << (j - 1) )][j - 1];
if(dep2[a] < dep2[b]) st[i][j] = a;
else st[i][j] = b;
}
}
}
int LCA(int a,int b){
int l = dfn[a], r = dfn[b];
if(l > r) std::swap(l, r);
int s = lg2[r - l + 1];
int x = st[l][s], y = st[r - (1 << s) + 1][s];
return dep2[x] < dep2[y] ? app[x] : app[y];
}
int dist(int x, int y){
return dep[x] + dep[y] - 2 * dep[LCA(x, y)];
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具