[dp优化] CF1582F2

posted on 2023-11-08 11:22:48 | under 未分类 | source

题意

给出序列 \(a\),求它的所有递增子序列的异或和?

\(n\le 1e6,0\le a\le5000\)

思路

值域很小,那很容易有一个 \(O(nv)\) 的暴力。\(f_i\) 记录异或和为 \(i\) 时的最小结尾,大力转移即可。再上些玄学优化便通过了考场数据。

然后考虑优化。发现这个状态定义太 fw 了,异或值不是呈区间的形态分布的。

故考虑修改状态,加上 结尾元素 这一维,定义 \(f_{i,j}\) 表示结尾元素 \(<i\) 且异或和为 \(j\) 的子序列是否存在。朴素复杂度 \(O(nv^2)\),但貌似很能优化。

然后很容易发现,当同一个 \(a\) 多次出现时,有些 \(f_{a,j}\) 会被遍历多次,显然只需遍历一次即可。

那么有优化思路:开动态数组 \(b_a\) 记录 \(j\),每次对 \(a\) 操作完后直接清空即可。复杂度均摊正确。

接着考虑优化转移:\(\forall p>a,a \to f_{p,a\bigoplus j}\)

不难发现这是个后缀。那么为了避免标记重复的 \(p\),可以考虑 \(r_j\) 表示下次标记时直接从 \(f_{r_j,p}\) 开始即可。复杂度均摊正确。

那么优化后 \(O(nv^2)\to O(n+v^2)\),可以通过。

此题很好体现了 及时删去重复状态 的优化思路。

小 trick 记录:

  • 转移式与后缀有关时可以仿照此题开 \(r\) 数组。

  • 及时更换状态表示,使其容易优化。

posted @ 2026-01-12 20:00  Zwi  阅读(3)  评论(0)    收藏  举报