对于每一步跳跃,我们要预处理一个二维数组f(father)f[x][i],表示对于当前的x结点,往上跳2^i个祖先,特别的,像数学中的,f[x][0]就是x的一代祖先。于是我们要用一个dfs预处理来解决这个f数组。后面我们会提到; 处理完f数组,那就很简单了。 输入x和y,表示要求结点x和结点y的LCA,那么我们开始求LCA: 对...
在最后返回的时候,返回fa[x][0]即为答案 intlca(intx,inty){if(dep[x] < dep[y])swap(x,y);while(dep[x] > dep[y]) x = fa[x][lg[dep[x] - dep[y]] -1];if(x == y)returny;/// big -> smallfor(intk = lg[dep[x]] -1;k >=0;k --){if(fa[x][k] != fa[y][...
LCA: LCA利用倍增后的数组进行二进制拆分,当depth[u],depth[v]不相同时,让depth[u],depth[v]相同,如果u==v说明最近公共最祖先时u,如果不相等,就在同一深度进行二进制差分式倍增,然后最终得到pre[u...
在树上倍增中,我们用 $f[j][i]$表示第$j$号节点,跳了$2^j$步所能到达的节点 $deep[i]$表示$i$号节点的深度 然后用这两个数组瞎搞搞就能整出LCA来啦 众人::wrench: :hammer: :hocho: 实现 deep&&f[i][0] 首先,$f[i][0]$(也就是一个节点的上面的节点)容易求得,只要对整棵树进行一边dfs...
当然它的作用不仅限于求LCA,还可以维护节点的很多信息 求LCA的方法除了倍增之外,还有树链剖分、离线tarjan ,这两种日后再讲(众人:其实是你不会吧:unamused:。。。) 思想 树上倍增嘛,顾名思义就是倍增 相信倍增大家都不默认,著名的rmq问题的O(n∗logn)的解法就是利用倍增实现的 ...
(RMQ 区间最值问题)给定序列 a0,… , an-1,和 m 次询问,每次询问给定 l, r,求max {al,… , ar}。 为了解决该问题,有一个算法叫 the Method of Four Russians,其时间复杂度为0(n + m),步骤如下: • 建立 Cartesian(笛卡尔)树,将问题转化为树上的 LCA(最近公共祖先)问题。 • 对于 LCA ...
考虑其他, 我们思考这么一个问题: 对于两个深度不同的结点, 把深度更深的那个向其父节点迭代, 直到这个迭代结点和另一个结点深度相同, 那么这两个深度相同的结点的Lca也就是原两个结点的Lca. 因此第二种情况转化成第一种情况来求解Lca是可行的. 这里我们使用倍增法以最快的速度找到相同的深度,然后开始求LCA。
注意倍增求LCA适用于询问多的情况,不然光在预处理上花的时间就已经够多了(如果只有一两个询问,直接暴力就好了) 当然,这个倍增算法判断条件是若干级祖先是否相等。 同样,点uu,vv的LCA还满足它是其中一个点的最近的一个祖先,满足uu,vv都在它的子树中。
第一种:树上倍增 f[x,k]表示x的2^k辈祖先,即x向根结点走2^k步达到的结点。 初始条件:f[x][0]=fa[x] 递推式:f[x][k]=f[ f[x][k-1] ][k-1] 一次bfs预处理f数组(nlogn),然后每次询问都可以在(logn)时间内求出x,y的lca 求lca的步骤 ...
LCA就是最近公共祖先,比如 节点10和11的LCA就是8,9和3的LCA就是3。 我们这里讲一下用树上倍增来求LCA。 大家都可以写出暴力解法,两个节点依次一步一步往上爬,直到爬到了相同的一个节点。 二树上倍增就是对暴力的优化,改成了一次爬好几步。