连续段 DP 学习笔记
一种用于统计符合特定条件排列个数的 DP 模型,这里的条件和具体位置无关,一般是相邻元素的大小关系限制。
考虑问题:统计 \([1,n]\) 的全排列有多少种。
考虑对某一个排列的构造方案:\([4,2,3,5,1,6]\)。我们从小到大插入元素,并且规定:如果插入的元素中出现两个相邻的,她们必须合并成一个块。并且时刻保持相对位置与结果一样。
-
加入 \(1\),序列为 \([1]\),共 \(1\) 段。
-
加入 \(2\),序列为 \([2, 1]\),共 \(1\) 段。
-
加入 \(3\),序列为 \([{2,3}, 1]\),共 \(2\) 段。
-
加入 \(4\),序列为 \([{4, 2, 3}, 1]\),共 \(2\) 段。
-
加入 \(5\),序列为 \([{4, 2, 3, 5, 1}]\),共 \(2\) 段。
-
加入 \(6\),序列为 \([{4,2,3,5,1,6}]\),共 \(1\) 段。
其实,按照这种规则构造一个排列,每种排列和每种构造方案是一一对应的,因此,我们可以 DP 统计一共有多少种构造。
于是,我们设计状态 \(f(i, j)\) 代表插入了 \([1,i]\),目前分为 \(j\) 段的总方案数。
那么考虑加入 \(i + 1\),有以下三种转移情况:
-
\(i + 1\) 自成一段,有 \((j + 1) \cdot f(i, j) \to f(i + 1, j + 1)\)。
-
\(i + 1\) 吸附在一段上,有 \(2j \cdot f(i,j) \to f(i + 1, j)\)。
-
\(i + 1\) 合并两段,有 \((j - 1) \cdot f(i, j) \to f(i + 1, j - 1)\)。
显然最终元素都是相邻的,所以只有一段,答案为 \(f(n, 1)\),在这个没有任何限制的情况下,显然 \(f(n, 1) = n!\)。
那么接下来加入限制:排列必须形如 \(...p_i < p_{i + 1} > p_{i + 2} < p_{i + 3}..., p_1 = s, p_n = t\)。
此时,连续段 DP 的作用便体现出来了:因为插入元素时,我们只考虑她两边的数的大小,因此块内被包裹的元素可以不用考虑,直接等价合并。
考虑加入 \(i + 1 \neq s, t\),考虑三种情况:
-
\(i + 1\) 自成一段,有 \((j + 1 - [i + 1 > s] - [i + 1 > t]) \cdot f(i, j) \to f(i + 1, j + 1)\)。
-
\(i + 1\) 被吸附在一段上,因为 \(i + 1\) 不是头/尾,所以只能吸附在中间 \(2(j - 1)\) 个位置上,但是如果不合并她左右的区间,那么在之后的添加中一定会出现连续两个上升/下降,故不存在这种转移。
-
\(i + 1\) 合并两段,有 \((j - 1) \cdot f(i, j) \to f(i + 1, j - 1)\)。
答案是 \(f(n, 1)\)。

浙公网安备 33010602011771号