CF201D - Brand New Problem 题解

首先吐槽一下为什么远古 CF 的题都这么奇怪……题面内容、输入、输出都非常恶心,让人很不爽……不过这道题倒是蛮好的(


Portal

首先映入脑帘的是一个状压 DP:\(dp_{i,j}\) 表示当前考虑到第 \(i\) 位,bitmask \(j\) 内的单词都被选的时候的最小逆序对数。转移就看当前这位选不选,\(\mathrm O(1)\)。这样显然光空间就 \(\mathrm O(k2^n)\) 了。

然后我想的是,从 5e5 里面只选 \(n\) 个,那绝大多数都是没用的,能不能找点什么性质把一定没用的给筛掉,这样可以减小 \(i\) 的值域。我想了一天,没想出来一个做法,然后就去看题解了(

注意到题解里的这样一句话:「Let's make use of a standard technique: make the value of DP a new parameter and make one of the existing parameters the value of DP.」(然后后面的笑脸「😃」有些邪恶)。意思就是注意到 DP 值是逆序对数,是 \(\mathrm O(n^2)\) 的,非常小,显然要远小于 DP 数组的任意一维的定义域,于是我们考虑常用套路:调换 DP 数组的定义域和值域(这个套路在 809D 里也用到了,我怎么就还是不会呢)。这个大概要求 DP 值关于这维有单调性,那么用 bitmask 那维来换显然是不行的,难道记录逆序对数等于某个数的任意一个 bitmask?那就显然无法转移了。但是第一维有单调性。于是我们考虑 \(dp_{i,j}\) 表示逆序对数等于 \(i\),bitmask 为 \(j\) 的最小满足要求的前缀的位置(其实 809D 也大概差不多是这个意思)。

突破了瓶颈,接下来就好办了。考虑如何转移,我们枚举最后一位的单词,然后不难得到上一个 bitmask(和所对应逆序对数,这个要减去前面那些对当前这个单词的贡献)所对应的最小前缀,然后根据贪心显然是找那个前缀后面的第一个这个字符,转移就可以了。这个每个位置的后面第一个每个字符可以预处理出来,那么复杂度就是 \(\mathrm O\!\left(m(kn+2^nn^3)\right)\),看起来挺大的,但实际常数算是小的,而且时限 5s。

code

posted @ 2020-12-02 19:31  ycx060617  阅读(92)  评论(0编辑  收藏  举报