前言

在做树上问题时,我们经常会遇到 \(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的更多相关文章

  1. [板子]倍增LCA

    倍增LCA板子,没有压行,可读性应该还可以.转载请随意. #include <cstdio> #include <cstring> #include <algorithm ...

  2. 洛谷P3128 [USACO15DEC]最大流Max Flow [倍增LCA]

    题目描述 Farmer John has installed a new system of  pipes to transport milk between the  stalls in his b ...

  3. Gym100685G Gadget Hackwrench(倍增LCA)

    题目大概说一棵边有方向的树,q个询问,每次询问结点u是否能走到v. 倍增LCA搞即可: 除了par[k][u]表示u结点往上走2k步到达的结点, 再加上upp[k][u]表示u结点往上走2k步经过边的 ...

  4. Codeforces 418d Big Problems for Organizers [树形dp][倍增lca]

    题意: 给你一棵有n个节点的树,树的边权都是1. 有m次询问,每次询问输出树上所有节点离其较近结点距离的最大值. 思路: 1.首先是按照常规树形dp的思路维护一个子树节点中距离该点的最大值son_di ...

  5. hdu 4674 Trip Advisor(缩点+倍增lca)

    花了一天半的时间,才把这道题ac= = 确实是道好题,好久没敲这么长的code了,尤其是最后的判定,各种销魂啊~ 题目中给出的条件最值得关注的就是:每个点最多只能在一个环内->原图是由一个个边连 ...

  6. Tsinsen A1505. 树(张闻涛) 倍增LCA,可持久化线段树,DFS序

    题目:http://www.tsinsen.com/A1505 A1505. 树(张闻涛) 时间限制:1.0s   内存限制:512.0MB    总提交次数:196   AC次数:65   平均分: ...

  7. codevs 1036 商务旅行 (倍增LCA)

    /* 在我还不知道LCA之前 暴力跑的SPFA 70分 三个点TLE */ #include<iostream> #include<cstdio> #include<cs ...

  8. hdu 2586 How far away ?倍增LCA

    hdu 2586 How far away ?倍增LCA 题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=2586 思路: 针对询问次数多的时候,采取倍增 ...

  9. 洛谷P4180 [Beijing2010组队]次小生成树Tree(最小生成树,LCT,主席树,倍增LCA,倍增,树链剖分)

    洛谷题目传送门 %%%TPLY巨佬和ysner巨佬%%% 他们的题解 思路分析 具体思路都在各位巨佬的题解中.这题做法挺多的,我就不对每个都详细讲了,泛泛而谈吧. 大多数算法都要用kruskal把最小 ...

  10. 洛谷P2633 Count on a tree(主席树,倍增LCA)

    洛谷题目传送门 题目大意 就是给你一棵树,每个点都有点权,每次任意询问两点间路径上点权第k小的值(强制在线). 思路分析 第k小......又是主席树了.但这次变成树了,无法直接维护前缀和. 又是树上 ...

随机推荐

  1. Head First Python 1-4章学习感悟

    一.学习知识总结 (1)迭代         range(起始值,结束值,步长):包含起始值,不包含结束值,步长为正数 (2)导入模块 from datetime import datetime (3 ...

  2. C#判断字符串是否是数字最简单的正则表达式

    if (theStr!= null)//注意加非空判断,否则报错 { System.Text.RegularExpressions.Regex rex = new System.Text.Regula ...

  3. 洛谷P2580(trie)

    第一行一个整数 n,表示班上人数.接下来 n 行,每行一个字符串表示其名字(互不相同,且只含小写字母,长度不超过 50).第 n+2 行一个整数 m,表示教练报的名字.接下来 m 行,每行一个字符串表 ...

  4. bzoj 2827: 千山鸟飞绝

    2827: 千山鸟飞绝 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 802  Solved: 228[Submit][Status][Discuss ...

  5. ios一个自定义的下拉多选菜单

    前段时间项目刚好要做到条件筛选菜单,正好找到一些别人写的,结合自己实际需求进行优化修改,一个实用的多条件筛选菜单,根据其他的下拉进行一些改进. 点击后返回点击文字显示 github地址:https:/ ...

  6. web综合案例03

    web综合案例03 web综合案例03 web综合案例03 web综合案例03 ... 待复习

  7. python依赖文件

    生成 pip freeze >requirements.txt 安装 pip install -r requirements.txt

  8. Sharepoint 根据文件相对路径获取、操作SPFolder

    public AjaxResult LoadDocInfo(HttpContext httpContext) { var result = new ArrayList(); try { var org ...

  9. AngularJS模块——module

    angular.module('myApp',[]) 1.定义模块 2.第一个参数:定义的模块名: 3.第二个参数:依赖列表,也就是可以被注入到模块中的对象列表:依赖的这些模块需要在本模块加载之前由注 ...

  10. Python+Selenium----使用HTMLTestRunner.py生成自动化测试报告2(使用PyCharm )

    1.说明 在我前一篇文件(Python+Selenium----使用HTMLTestRunner.py生成自动化测试报告1(使用IDLE ))中简单的写明了,如何生产测试报告,但是使用IDLE很麻烦, ...