线头 DP 学习笔记

线头 DP 学习笔记

线头 DP 主要是指维护一些左闭右开的线段的 DP,在这里可能右端点没有确定,只确定了左端点,每次操作可以延伸一个线段,或者确定一个右端点

找不到板子了

直接例题引入

CF626F

有一个长度是 $ n $ 的数组 $ a $,分成若干组,极差总和不超过 $ k $,求方案数

这个题我们先考虑朴素 DP

设 $ dp_{i, j, k} $ 表示前 $ i $ 项选了 $ j $ 个,极差是 $ k $,但不能确定选到哪一组,所以也不能记录极差

于是记录每组,就是 $ dp_{i, j, k} $,表示前 $ i $ 个,选了 $ j $ 组,当前极差是 $ k $

但是转移需要枚举加入哪一组,这样也没法转移

所以引入线头 DP

我们先做一步转化,我们先按照 $ a_i $ 从小到大排序,然后转化求极差的部分

我们在一组中插入 $ a_i $,上一位是 $ a_j $,那么极差就要加上 $ a_i - a_j $,自行理解

本题中无法记录上一个数 $ a_j $,所以我们直到确定了右端点再加入贡献即可

然后把刚刚的 DP 第二维 $ j $ 改成表示当前有 $ j $ 组还没有确定右端点

这样可以线头 DP

考虑转移,我们可以做以下操作:

  1. 延伸一个右端点

  2. 确定一个右端点

  3. 新开一个左端点

  4. 自己做一组

转移分别如下:

  1. 延伸一个右端点

$ dp_{i, j, k} += dp_{i - 1, j, k} \times j $

  1. 确定一个右端点

$ dp_{i, j, k} += dp_{i - 1, j + 1, k + a_i} \times (j + 1) $

  1. 新开一个左端点

$ dp_{i, j, k} += dp_{i - 1, j - 1, k - a_i} $

  1. 自己做一组

$ dp_{i, j, k} += dp_{i - 1, j, k} $

然后我们做完了

posted @ 2024-08-15 08:48  __Tzf  阅读(1)  评论(0编辑  收藏  举报