DFS序求LCA详解 1. DFS序的概念 DFS序(Depth-First Search Order)表示对一棵树进行深度优先搜索得到的节点序列。在DFS遍历过程中,每个节点在首次访问时被记录一次,在某些实现中,当回溯到该节点时,也会再次记录。但通常,我们更关心首次访问的顺序,因为这足以确定节点的相对位置关系。 2. 如何通过DFS序求LCA 给定...
对比DFS 序和欧拉序,不仅预处理的时间常数砍半(欧拉序 LCA 的瓶颈恰好在于预处理,DFS 是线性),空间常数也砍半(核心优势),而且还更好写(对于一些题目就不需要再同时求欧拉序和 DFS 序了),也不需要担心忘记开两倍空间,可以说前者从各个方面吊打后者。 对比DFS 序和倍增,前者单次查询复杂度更优。 对于DFS 序...
首先遍历一遍整棵树,可以得到整棵树的 DFS 序和每个点的时间戳(记为dfndfn)。 考虑两个点u,vu,v,求这两个点的 LCA 。不妨设dfnu<dfnvdfnu
[N + 10]; // 在 dfs 序列上维护 rmq 求 lca int clk, bgn[N + 10]; int lg[N * 2 + 10], f[MAXP][N * 2 + 10]; void dfs(int sn, int fa) { f[0][++clk] = sn; bgn[sn] = clk; for (int i = 0; i < e[sn].size(); i++) { int fn = e[sn][i]; if (...
BZOJ2819: Nim【树状数组+dfs序+倍增求LCA】 树上的Nim取石子游戏。 说白了就是,维护一棵树,支持:修改点权,询问一条路径上点权的xor值是否为零。 可以用树链剖分做。但是介于n和q都50w这么大感觉常数很DT。。 既然它只修改点的话,影响到的只是它这棵子树。那么很容易就想到了dfs序。这个子树就是连续一...
// HihoCoder - 1069.cpp /* 一颗树结构求lca: 1.输入一串查询序列,离线Tarjan算法一次算出 2.一次初始化,之后每次查询快速得到答案,压DFS序之后,每次查询区间深度最小值 3.初始化ST表,每次倍增求 */ #include <iostream> #include <stdio.h> #include <algorithm> #include <vector> #include using nam...
一堆结点的 lca 是 dfs 序里最左和最右两个结点的 lca(这个结论建虚树的时候会用)。 因而还需要对以结点为下标,以cmp_by_dfn为比较函数,再分别建两组 st 表,加上 lca 自己的 st 表一共有 3 组。 询问的时候讨论一下删左还是删右即可。
学点分树,发现不会询问复杂度O(1)O(1)的 LCA。于是被迫递归式学习。 我们设dfnidfni表示点ii在 dfs 过程中第几个被访问到,把点按访问到的顺序排序得到的序列叫 dfs 序。 考虑uu和vv在 dfs 序上的位置之间的这一段序列有什么。 设lca(u,v)=x,dfnu<dfnvlca(u,v)=x,dfnu...
DFS序求LCA原理: 我们令u点在dfs序中出现的位置为时间戳dfn[u]。 设dfn[u]<dfn[v]。 当u不是v的祖先时,设d为lca(u,v)。 观察到dfn[d]<dfn[u]
DFN序:对一棵树进行深度优先搜索DFS得到的结点序列,即深度优先搜索DFS的访问顺序。该表述不一定严谨,建议百度 ST表(Sparse Table,稀疏表) 算法概述 引理1.1 在DFN序 中祖先一定出现后代之前。 证明:由遍历顺序易得 考虑一树上的两个节点x,y的最近公共祖先d,设x的 DFN序小于等于y的 DFN序。