树专题训练
- 题目描述:给定一棵树,需选定一个大小为\(k\)的连通块,最小化非连通块的点到连通块的最大距离。其中距离定义为点与连通块中所有点的路径最小值。
- 数据范围:\(1\le k < n \le 10^5\)。
首先找到树的直径,以其中点为根,这样做的好处是连通块一定是包含根节点的一个连通块,之后直接贪心求解,如果子节点能使答案减小选上即可。
关于树的直径,可以两次dfs找最远点,也可以用树形dp做。
时间复杂度\(O(n)\)。
- 题目描述:以斐波那契数列的兔子模型,按兔子出生顺序对所有兔子进行编号,若两对兔子同时出生则父母编号小的兔子编号更小。按父子关系连边形成一棵树。现有\(m\)组询问,每次询问两只兔子\(a_i\)和\(b_i\)的最近公共祖先。
- 数据范围:\(m\le 3\times10^5\),\(a_i,b_i\le10^{12}\)。
根据关系图可以得到一个结论:父亲与儿子节点标号正好相差斐波那契数列中的某值,且这个值是小于儿子节点中最大的那个,下面有一个简单的证明。
在第\(k\)个月后一共有\(fib_k\)只兔子,其中\(fib_{k-1}\)只具有生育能力,将在第\((k+1)\)个月生下\(fib_{k-1}\)只兔子,其编号为\(fib_{k}+1,\cdots,fib_k+fib_{k-1}\),其父亲编号正好是\(1,\cdots,fib_{k-1}\),故得证。
由于\(fib_k > 2fib_{k-2}\),即斐波那契数列是指数级膨胀的,因此树高是\(O(\log v)\)级别的,暴力向上跳找lca即可。
时间复杂度\(O(n\log^2 v)\)。
- 题目描述:给定一颗\(n\)个点的森林,有\(m\)次询问,求出编号为\(v\)的点有多少个\(p\)级表亲。两个点称为\(k\)级表亲当且仅当存在一个点同时是他们的\(k\)级祖先。
- 数据范围:\(1\le n,m\le 10^5\)。
树上启发式合并(dsu on tree)的模板题。
考虑暴力做法,用dfs统计信息,当dfs到平行的下一课子树时,之前的信息就需要清掉,而当回到父亲节点统计其信息时,又需要将所有子树信息重新加回来,从而造成浪费。但根据这一逻辑,我们发现实际上dfs到的最后一个子树信号是不需要清空的,因此想办法把信息最多的子树(重儿子)最后一个dfs即可。
时间复杂度\(O(n\log n)\)。
- 题目描述:给定一颗有根树,点有点权,有\(m\)个操作,每次给定一个值\(t_i\),可以不操作,也可以任选一点使其到根的路径上所有点权都向上移(即父亲权值变为儿子权值),根节点权值丢掉,同时该点权值变为\(t_i\),求操作后树的最大总权值。
- 数据范围:\(2\le n \le 5000\),\(1\le m \le5000\)。
首先注意到操作的顺序使不重要的,任意的操作顺序都能得到同样的结果,因此可以贪心地将\(t_i\)从大到小排序,最后肯定取它的一段前缀。
观察题意,发现要舍弃的是包括根节点(即节点1)在内的一个连通块内的权值,那么设\(f_{i,j}\)表示子树\(i\)中舍弃\(j\)个节点的最小权值和,若节点x有一个儿子y,那么有转移方程:
这是边dfs边做的,因此可以包含所有子树信息,同时注意需从后往前枚举,防止造成重算,跟01背包倒着枚举同理。
设\(\{T_i\}\)是\(\{t_i\}\)的前缀和,\(S\)为最初点权和,最终答案即为\(\max_{i=0}^n\{S+T_i-f_{1,i}\}\)。
时间复杂度\(O(n^2)\)。