[CF 2078F] Binary Subsequence Value Sum
前言
感觉很强, 当然必须自己推一推更好
据据检验
- 定义操作 (约束) 和开销 / 收益, 要求最值化开销 / 收益
- 模拟操作, 找性质
- 将约束条件数学化
- 方便高效维护
- 最优化问题的瓶颈, 考虑找最优解的性质来处理
- 逐元素处理
- 先找到统一的构造方式
- 直接处理
- 推导动态规划
- 枚举开销对应的值\((\)超过 \(x\) / 不大于 \(x\) / 长度为 \(x\)\()\) , 然后考虑对于这个值进行
- 贪心
- 判断合法性
- 往往拥有单调性
- 先找到一组简单的合法解, 然后在基础上进行调整, 使其花销更优
- 要求一个数列的多个部分 \((\)前缀, 子串 \(\cdots\)\()\) 的成本
- 贪心找到最优操作的构造方法, 加上优化 / 找共同点
- 往往可以形似 \(\rm{dp}\) , 继承之前的左端点/右端点的值
- 一般状态形似 \(f_l\) 表示以 \(l\) 开头区间的贡献, \(f_r\) 表示以 \(r\) 结尾区间的贡献等等
- 子序列
- 推导关于序列性质的式子 \((\)例如: \(1, 0\) 的个数\()\)
- 子序列 \(\rm{dp}\)
- 针对当前已经有的子序列进行插入而非根据位置选择
- 一般分为插入之前的和新开两类
- 跳跃 / \(\cdots\) 等建图问题
- 考虑优化建图
- 动一个点要求计算每一个位置的答案
- 前后缀类拼接问题
- 预处理前后缀, 然后拼拼拼
- 区间包含数量问题
- 前后缀类拼接问题
思路
题意
给定一个 串
定义一个前后划分方案的花费是前半部分 的个数减去 的个数乘以后半部分 的个数减去 的个数
形式化的来讲, 设 为区间 中 的个数, 为区间 中 的个数
那么分割点 的贡献为
次修改, 每次取反 串的某一位
对于每次修改和初始情况, 输出当前 串的所有子序列最大花费之和
先找对于确定子序列的性质
考虑子序列共有 \(cnt_1\) 个 \(1\) , \(cnt_0\) 个 \(0\), 不难发现在过程中, \(\Big[\textrm{one}(1, i) - \textrm{zero}(1, i)\Big]\) 可以取遍 \(0 \sim cnt_1 - cnt_0\)
不妨令 \(k = \Big[\textrm{one}(1, i) - \textrm{zero}(1, i)\Big]\) , 贡献为 \(k \times \Big(cnt_1 - cnt_0 - k\Big)\)
不难发现 \(\displaystyle k \times \Big(cnt_1 - cnt_0 - k\Big)\) 在 \(\displaystyle k = \left\lfloor \frac{cnt_1 - cnt_0}{2} \right\rfloor\) 时取到最大值 \(\displaystyle \left\lfloor \frac{cnt_1 - cnt_0}{2} \right\rfloor \left\lceil \frac{cnt_1 - cnt_0}{2} \right\rceil\)
证明
因为
一定, 越小, 显然 越大
因此我们只要知道了 \(cnt_0, cnt_1\) , 可以 \(\mathcal{O} (1)\) 的计算出子序列的贡献
方法 \(1\)
又发现 \(01\) 串的子序列, 本质上就是挑选一些 \(1, 0\) 组成的
因此考虑用组合意义表示
考虑当前串串有 \(cnt_1\) 个 \(1\) , \(cnt_0\) 个 \(0\)
发现一个有 \(c_1\) 个 \(1\) , \(c_0\) 个 \(0\) 的子序列, 总共有 \(\displaystyle{cnt_1 \choose c_1}{cnt_0 \choose c_0}\) 个, 也就是选取任意 \(0, 1\) 子集
问题变为
然后这个似乎可以化简, 但是我不是数学牢大, 不管了
方法 \(2\)
考虑 似 \(\rm{dp}\) 做法
先对于原串处理, 不管修改
前置是对
的处理, 不难发现可以按 \(c_1 - c_0\) 奇偶性分开
- \(c_1 - c_0 = 2k\)
\(= k^2\) - \(c_1 - c_0 = 2k + 1\)
\(= k(k + 1)\)
令 \(f(i)\) 表示串串前 \(i\) 长度部分的子序列 \((\)不包括空序列\()\) 贡献之和
考虑 \(f(i)\) 应该怎么计算, 不难发现应该分成在之前的 \(f(i - 1)\) 中插入和新开以及直接继承之前的三种
- 在之前的 \(f(i - 1)\) 中插入
- 这一位为 \(1\)
- 之前 \(c_1 - c_0 = 2k\)
\(\displaystyle\Delta = k(k + 1) - k^2 = k = \frac{c_1 - c_0}{2}\) - 之前 \(c_1 - c_0 = 2k + 1\)
\(\displaystyle\Delta = (k + 1)^2 - k(k + 1) = k + 1 = \frac{c_1 - c_0 + 1}{2}\)
- 之前 \(c_1 - c_0 = 2k\)
- 这一位为 \(0\)
- 之前 \(c_1 - c_0 = 2k\)
\(\displaystyle\Delta = k(k - 1) - k^2 = -k = -\frac{c_1 - c_0}{2}\) - 之前 \(c_1 - c_0 = 2k + 1\)
\(\displaystyle\Delta = k^2 - k(k + 1) = -k = -\frac{c_1 - c_0 - 1}{2}\)
- 之前 \(c_1 - c_0 = 2k\)
- 这一位为 \(1\)
- 新开
- 新开一个 \(1\)
贡献为 \(0\) - 新开一个 \(0\)
贡献为 \(0\)
- 新开一个 \(1\)
- 直接继承
即直接加上 \(f(i - 1)\)
因此我们应当维护状态:
-
值应当表示串串前 \(i\) 长度部分的子序列 \((\)不包括空序列\()\) 贡献之和
-
维护之前 \(c_1 - c_0 = 2k + 1\) 的数量
发现直接可以用 \(2^{i - 1}\) 表示, 考虑一些证明
首先需要知道的是, \(c_1 - c_0 = 2k + 1\) 仅当 \(c_1, c_0\) 奇偶性不同
可以视作在 \(cnt_1\) 个 \(1\) 中选择 \(c_1\) 个 \(1\) , 在 \(cnt_0\) 个 \(0\) 中选择 \(c_0\) 个 \(0\)
有如下证明证明
首先,我们考虑一个大小为 的集合,其子集总数为 。我们需要证明其中大小为奇数的子集个数为 。
方法一:二项式定理
利用二项式定理展开 ,当 时,得到:
当 时,得到:
将这两个式子相加和相减:
由此可得:
方法二:数学归纳法
• 基例:当 时,集合的子集为 和自身,其中奇数子集个数为 1,即 ,成立。
• 归纳假设:假设当 时,奇数子集个数为 。
• 归纳步骤:考虑 的集合,新增一个元素 。不包含 的奇数子集有 个,包含 的奇数子集数目等于原集合中偶数子集的数目 。因此总数为 ,即 ,成立。方法三:构造配对
固定一个元素 ,将子集分为包含 和不包含 的两类。对于不包含 的子集 ,若 为奇数,则 为偶数,反之亦然。这样的配对使得每对中恰好有一个奇数和一个偶数子集,总数为 对,奇数子集数目为 。
结论
无论使用哪种方法,结果都表明大小为奇数的子集个数为 。
由此可知选出同为奇数和同为偶数的 \(c_1, c_0\) 各有 \(2^{cnt_1 - 1} \times 2^{cnt_0 - 1}\) 种, 一共有 \(2^{cnt_1 - 1 + cnt_0 - 1 + 1} = 2^{i - 1}\) 种, 那么选出奇偶性不同的也有 \(2^{i - 1}\) 种
哎好像整复杂了, 无敌
肯定有更好的方法, 但是我是弱智啊! -
维护之前 \(c_1 - c_0\) 之和
不妨设为 \(g(i)\) 这样方便转移- 在之前的 \(g(i - 1)\) 中插入
- 这一位为 \(1\)
\(\displaystyle\Delta = g(i - 1) + 2^i - 1\) - 这一位为 \(0\)
\(\displaystyle\Delta = g(i - 1) - 2^i + 1\)
- 这一位为 \(1\)
- 新开
- 新开一个 \(1\)
贡献为 \(1\) - 新开一个 \(0\)
贡献为 \(-1\)
- 新开一个 \(1\)
- 直接继承
即直接加上 \(g(i - 1)\)
总的来说, 可以表述成
- 这一位为 \(1\)
\(\displaystyle\Delta = g(i - 1) + 2^i\) - 这一位为 \(0\)
\(\displaystyle\Delta = g(i - 1) - 2^i\) - 直接继承
即直接加上 \(g(i - 1)\)
- 在之前的 \(g(i - 1)\) 中插入
总的来说, 我们发现完全不是 \(\rm{dp}\) 的模样
这三个东西可以简单表示, 具体的
设 \(cnt\) 表示之前 \(c_1 - c_0 = 2k + 1\) 的数量
\(sum\) 之前 \(c_1 - c_0\) 之和
\(res\) 表示 \(f(i)\) 的值
- 当前为 \(1\)\[ \begin{align*} \begin{cases} res \leftarrow 2res + \dfrac{sum + cnt}{2} \\ cnt \leftarrow 2cnt \\ sum \leftarrow 2(sum + cnt) \end{cases} \end{align*} \]
- 当前为 \(0\)\[ \begin{align*} \begin{cases} res \leftarrow 2res - \dfrac{sum - cnt}{2} \\ cnt \leftarrow 2cnt \\ sum \leftarrow 2(sum - cnt) \end{cases} \end{align*} \]
显然用矩阵维护操作即可, 基础上做矩阵线段树
总结
特殊的性质:
每次 \(\Delta = 1, 0, -1\) , 一定可以取遍极值
一般出现在
- 单位移动 \(\&\) 出现次数
\(01\) 串子序列可以转化成组合问题
数学上奇偶性的问题往往可以拆成 \(2k, 2k + 1\) 的问题方便表示
这种全子序列的信息往往是固定的, 方便简单递推
反而如果对子序列信息有约束, 才是 \(\rm{dp}\) 发力

浙公网安备 33010602011771号