Loading

连续段 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)\)

posted @ 2026-08-20 22:22  Trent900  阅读(25)  评论(2)    收藏  举报