倍增LCA
前言
在做树上问题时,我们经常会遇到 \(LCA\)(最近公共祖先)问题。曾经的我遇到这类问题只会\(O(n)\)暴力求解,学了倍增\(LCA\),就可以\(O(logn)\)解决了。
简介
倍增\(LCA\),顾名思义,就是利用倍增来求解\(LCA\)(这真的是简介)。
主要思路
- 我们可以用\(fa[i][j]\)来记录\(i\)的第\(2^j\)个祖先。
- 然后,对于每一次询问\(LCA(x,y)\),我们先找到\(x\)和\(y\)最近的深度相同的祖先。
- 接下来,我们先倍增找到最近的\(x\)和\(y\)的刚好为\(2^j\)的公共祖先。
- 然后,我们不断减小\(j\),若当前\(fa[x][j]!=fa[y][j]\),我们就更新\(x=fa[x][j]\),\(y=fa[y][j]\),这样就可以保证修改后\(fa[x][j]=fa[y][j]\)了。
一个简短的证明
因为我们已经保证修改前的\(fa[x][j+1]=fa[y][j+1]\)了
并且,显然可得,\(fa[fa[x][j]][j]=fa[x][j+1]\),\(fa[fa[y][j]][j]=fa[y][j+1]\)(\(x\)的第\(2^j\)个祖先的第\(2^j\)个祖先即为\(x\)的第\(2^{j+1}\)个祖先,\(y\)同理)
因此,修改后的\(fa[x][j]\)和\(fa[y][j]\)就等同于修改前的\(fa[x][j+1]\)和\(fa[y][j+1]\)
得证,我们可以保证修改后\(fa[x][j]=fa[y][j]\)
- 最后返回\(fa[x][0]\)即可。
代码
inline int LCA(int x,int y)//求x和y的最近公共祖先
{
register int i;int k;
if(dep[x]<dep[y]) swap(x,y);//比较x和y的深度,选择深度较大的节点,寻找它的与深度较小的节点深度一样的祖先
for(i=0;dep[x]^dep[y];++i) if((dep[x]^dep[y])&(1<<i)) x=fa[x][i];//如上
if(!(x^y)) return x;//如果x==y,返回x
for(k=0;fa[x][k]^fa[y][k];++k);//我们先倍增找到最近的x和y的刚好为2^j的公共祖先
for(;k>=0;--k) if(fa[x][k]^fa[y][k]) x=fa[x][k],y=fa[y][k];//不断减小j,若当前fa[x][j]!=fa[y][j],我们就更新x=fa[x][j],y=fa[y][j]
return fa[x][0];//最后返回x的父亲
}
倍增LCA的更多相关文章
- [板子]倍增LCA
倍增LCA板子,没有压行,可读性应该还可以.转载请随意. #include <cstdio> #include <cstring> #include <algorithm ...
- 洛谷P3128 [USACO15DEC]最大流Max Flow [倍增LCA]
题目描述 Farmer John has installed a new system of pipes to transport milk between the stalls in his b ...
- Gym100685G Gadget Hackwrench(倍增LCA)
题目大概说一棵边有方向的树,q个询问,每次询问结点u是否能走到v. 倍增LCA搞即可: 除了par[k][u]表示u结点往上走2k步到达的结点, 再加上upp[k][u]表示u结点往上走2k步经过边的 ...
- Codeforces 418d Big Problems for Organizers [树形dp][倍增lca]
题意: 给你一棵有n个节点的树,树的边权都是1. 有m次询问,每次询问输出树上所有节点离其较近结点距离的最大值. 思路: 1.首先是按照常规树形dp的思路维护一个子树节点中距离该点的最大值son_di ...
- hdu 4674 Trip Advisor(缩点+倍增lca)
花了一天半的时间,才把这道题ac= = 确实是道好题,好久没敲这么长的code了,尤其是最后的判定,各种销魂啊~ 题目中给出的条件最值得关注的就是:每个点最多只能在一个环内->原图是由一个个边连 ...
- Tsinsen A1505. 树(张闻涛) 倍增LCA,可持久化线段树,DFS序
题目:http://www.tsinsen.com/A1505 A1505. 树(张闻涛) 时间限制:1.0s 内存限制:512.0MB 总提交次数:196 AC次数:65 平均分: ...
- codevs 1036 商务旅行 (倍增LCA)
/* 在我还不知道LCA之前 暴力跑的SPFA 70分 三个点TLE */ #include<iostream> #include<cstdio> #include<cs ...
- hdu 2586 How far away ?倍增LCA
hdu 2586 How far away ?倍增LCA 题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=2586 思路: 针对询问次数多的时候,采取倍增 ...
- 洛谷P4180 [Beijing2010组队]次小生成树Tree(最小生成树,LCT,主席树,倍增LCA,倍增,树链剖分)
洛谷题目传送门 %%%TPLY巨佬和ysner巨佬%%% 他们的题解 思路分析 具体思路都在各位巨佬的题解中.这题做法挺多的,我就不对每个都详细讲了,泛泛而谈吧. 大多数算法都要用kruskal把最小 ...
- 洛谷P2633 Count on a tree(主席树,倍增LCA)
洛谷题目传送门 题目大意 就是给你一棵树,每个点都有点权,每次任意询问两点间路径上点权第k小的值(强制在线). 思路分析 第k小......又是主席树了.但这次变成树了,无法直接维护前缀和. 又是树上 ...
随机推荐
- C#判断字符串是否是数字最简单的正则表达式
if (theStr!= null)//注意加非空判断,否则报错 { System.Text.RegularExpressions.Regex rex = new System.Text.Regula ...
- 消耗战——dp+虚树
题目 [题目描述] 在一场战争中,战场由 $n$ 个岛屿和 $n-1$ 个桥梁组成,保证每两个岛屿间有且仅有一条路径可达.现在,我军已经侦查到敌军的总部在编号为 $1$ 的岛屿,而且他们已经没有足够多 ...
- Gradle用户使用指南
转载请事先沟通,未经允许,谢绝转载. 1. 新工具介绍(Introduction) 能够复用代码和资源能够构建几种不同版本参数的应用能够配置.扩展.自定义构建过程1.1 为什么选择Gradle(Why ...
- jmeter-提取器之正则表达式提取器
在接口测试中,有很多的接口参数值是需要从上一个接口的返回值中获取的,这个时候就可以用正则表达式提取器啦 例如: 接口1 /user/login 返回{ "user_ticket" ...
- nagios客户端之nrpe3.2.1安装(Ubuntu)
1.删除dpkg安装的nrpedpkg -l | grep nrpedkpg -P nagios-nrpe-server 2.ubuntu下nrpe3.2.1安装 下载nrpe3.2.1的源码包:ht ...
- windows srver 显示桌面图标。
rundll32.exe shell32.dll,Control_RunDLL desk.cpl,,0
- 用POST方法上传文件
文件上传分为客户端和服务器端 客户端可以通过form表单进行上传 客户端使用html表单进行上传 enctype = "multipart/form-data"用来指定表单编码数据 ...
- Ehab and subtraction(思维题)
time limit per test 1 second memory limit per test 256 megabytes input standard input output standar ...
- spring boot与 spring.factories
spring boot启动加载过程 META-INF下面的spring.factories 解析@Configuration https://www.jianshu.com/p/346cac67bfc ...
- JS——jquery UI
1. draggable() 滑动条demo: <!DOCTYPE html> <html lang="en"> <head> <meta ...