loading...

7.21 决策单调性,代码实现

[北大集训 2018] ZYB 的游览计划

给定一棵树,定义 \(cost(S)\) 表示从 \(1\) 出发要求经过 \(S\) 中的所有点,最后回到 \(1\) 所经过边数的最小值。

给定 \(k\) 和排列 \(p\),将 \(p\) 划分为 \(k\) 个区间,求区间 \(cost(p[l,r])\) 的和最大值。

\(1 \le k \le n \le kn \le 2 \times 10^5\)

考虑 \(cost(S)\) 怎么求,容易发现就是建立起 \(S\) 的最小斯坦纳树的边数 \(\times 2\)。考虑虚数的构建,将点按照 dfn 序排序,则依序走是最优秀的。考虑使用 \(\tt set\) 维护插入删除。这个也 \(cost(p[l,r])\) 显然是满足四边形不等式的,使用 dp 决策单调性优化即可。复杂度 \(\mathcal O(nk \log^2 n)\)

[THUPC 2024 决赛] 转化

\(n\) 种物品和 \(m\) 种转化方式,第 \(i\) 种转化方式可以将第 \(a_i\) 种物品转化为 \(k_i\) 个互不相同的物品,其中第 \(j\) 个种类为 \(b_{i, j}\)

你有一些物品,第 \(i\) 种有 \(c_i\) 个,对于每一种特定的物品 \(d\),求出经过若干次如上转化后能得到的 \(d\) 物品数量最大值。如果能得到无限个该物品,则输出 infinity

\(1 \le n \le 100, 1 \le m \le 1000, 0 \le c_i \le 1000\)

对于每种转化方式建虚点,连向所有 \(b_{i,j}\),并让 \(a_i\) 连向该虚点。然后对于每个大小 \(>1\) 的强连通分量:

  • 如果有至少 \(2\) 条从虚点出发的边指向两个分量内的节点,则该强连通分量为 \(\infty\) 点。
  • 其余情况,如果要成环必然环内有虚点和物品点(实点):
    • 对于虚点连出去的边,后续节点全为 \(\infty\) 点。
    • 对于实点连出去的边,需要将该强连通分量视为实点进行 DAG 上的 DP。

强连通分量内的点可以共享同一个最大值(因为可以无限地传递)。建图的点数为 \(\mathcal O(n+m)\),边数为 \(\mathcal O(nm)\)

然后剩下的问题在 DAG 中进行。我们设 \(f_i\) 表示 \(i\) 号强连通分量所能输入的物品最大值,则 \(f_u = \sum _{x \in scc(u)}c_u+\displaystyle \sum _{v\to u} f_v\)。(?)

但问题是如果某个非无限点 \(u\) 有两个后继 \(v_1, v_2\)\(v_1, v_2\) 存在一个公共后继 \(w\),则 \(w\) 会接受到两个由 \(u\) 产生的贡献,然后 dp 就挂了。这里必须认识到实点到虚点是有选择性的,重新定义 dp,\(f_{u, i}\) 表示在 \(u\) 上放一个物品,最终可以在 \(i\) 上产生多少个物品。在 DAG 上 DP,复杂度为 \(\mathcal O(n^2m)\)。细节较多,于是我写了 \(\mathcal O(n^3m)\) 的松弛做法,不会 T。

[SWERC 2023] In-order

给定一棵二叉树的前序遍历和后序遍历的序列,以及中序遍历的一个区间。求可能的完整中序遍历的数量,对 \(999999937\) 取模。

\(n \le 500000\)

对于前序遍历和后序遍历分析可知道每个节点的儿子,且能够区分每个有两个儿子的节点的左/右儿子。

接下来只需要去关心只有一个儿子的点,记这些点的个数为 \(cnt\)

如果没有限制中序遍历的话,可以直接输出 \(2^{cnt}\)。下称已知中序遍历位置的点为关键点。

但是有限制,我们考虑把儿子变成左右儿子不影响儿子内部的中序遍历,只需要考虑父亲是放在这段序列的左边还是右边。钦定所有这种孤儿子放在左边。

接下来考虑到如果区间长度 \(\ge 2\),则所有中序遍历相邻点可以确认两相邻点的路径上的儿子选取方式。特判区间长度为 \(1\) 的情况,对于这一类情况,在刚刚钦定出来的中序遍历中算出与实际位置的位置差,考虑孤儿子的选择对于关键点位置的影响,则可以使用组合数计算。注意这一类情况必须特判仅有一个儿子的点恰好为关键点。

posted @ 2026-07-22 08:16  goldspade  阅读(2)  评论(0)    收藏  举报