team2012-D1-sol-0019

从 Trac 迁移的文章

这是从旧校内 Wiki 迁移的文章,可能存在一些样式问题,您可以向 memset0 反馈。

原文章内容如下:

=== 题目大意 ===
给出 n 个点, m 条边, 边有权值. 先求一个最小生成树. 然后在这个生成树上做查询: 每个点有一个值 b[i]. 每次查询给出两个端点 x 和 y, 求在树上从 x 点到 y 点这个结点序列中的 max{b[i]-b[j]|i在序列中在j的后面, 或者 i == j}.

=== 数据范围 ===
 * 1 <= n <= m <= 50000

=== 解题思路 ===
第一问求最小生成树用 prim 或者 kruskal 都行. 我是用 kruskal 的, 因为后面 tanjan 算法求 LCA 也要用到并查集.

第二问利用 tarjan 离线 LCA 算法来做树形 DP. 具体的可以参考 prowindy 学长的解题报告. 不过我没去看 prowindy 学长是如何完成查询的, 我自己是在访问完结点 x 的所有子结点, 函数要返回之前, 这时候算一下所有 LCA 是 x 的查询的 ans. 因为此时 x 是你所要查询的结点的根结点, 所以分别对起点和终点 find() 一下可以维护到 x 这段区间的值了. 思想和 tarjan 离线算法的思想差不多.

题目大意

给出 n 个点, m 条边, 边有权值. 先求一个最小生成树. 然后在这个生成树上做查询: 每个点有一个值 b[i]. 每次查询给出两个端点 x 和 y, 求在树上从 x 点到 y 点这个结点序列中的 max{b[i]-b[j]|i在序列中在j的后面, 或者 i == j}.

数据范围

  • 1 <= n <= m <= 50000

解题思路

第一问求最小生成树用 prim 或者 kruskal 都行. 我是用 kruskal 的, 因为后面 tanjan 算法求 LCA 也要用到并查集.

第二问利用 tarjan 离线 LCA 算法来做树形 DP. 具体的可以参考 prowindy 学长的解题报告. 不过我没去看 prowindy 学长是如何完成查询的, 我自己是在访问完结点 x 的所有子结点, 函数要返回之前, 这时候算一下所有 LCA 是 x 的查询的 ans. 因为此时 x 是你所要查询的结点的根结点, 所以分别对起点和终点 find() 一下可以维护到 x 这段区间的值了. 思想和 tarjan 离线算法的思想差不多.