CF1922F:Replace on Segment 题解

第一次AK div2,写篇题解纪念下。

这场应该是我打过最简单的div2了,曾经有一场做出C都能进前200,这场五题都有1000人。


做完C题之后去看榜,E题竟然比D题人多,看眼,诶?这不是原题吗,怎么Edu也有原题呀。

回来看D以为是神仙题,结果发现只是个O(n)的链表。

F:

题意:给你一个数列,每次可以选一个区间,如果这个区间没有k,你可以把所有数变成k,求整个数列变成同一个数的最小操作数。

这题数据范围是 n<=100,以CF的评测机来看 \(n^4\) 其实是可过的,但是发现jiangly只用了30ms,应该是有 \(n^3\) 的做法。

Solution:

区间操作全局最优,这里提供一个 \(n^4\) 的区间dp。

因为是区间刷漆嘛,所以我一开始设的状态是 \(f[l][r][k]\) 表示区间 \([l,r]\) 全是 k 的最小操作数。

怎么转移呢?左边区间全是某一个数,右边区间也全是某一个数,那么 \(f[l][r][k] = f[l][mid][x]+f[mid+1][r][y]+1\) 酱紫。

发现好像不对啊,这样的话相当于选取的区间只能包含同一个数。

于是增加一个状态 \(g[l][r][k]\) 表示区间全都不是 k ,如果我们先计算 f 再计算 g ,那么有如下转移:

f 数组:

\(f[l][r][k] = f[l][mid][k]+f[mid+1][r][k]\)

\(f[l][r][k] = f[l][mid][k]+g[mid+1][r][k]+1\)

\(f[l][r][k] = g[l][mid][k]+f[mid+1][r][k]+1\)

\(f[l][r][k] = g[l][mid][k]+g[mid+1][r][k]+1\)

g 数组:

\(g[l][r][k] = g[l][mid][k]+g[mid+1][r][k]\)

\(g[l][r][k] = f[l][mid][k]+g[mid+1][r][k]+1\)

\(g[l][r][k] = g[l][mid][k]+f[mid+1][r][k]+1\)

\(g[l][r][k] = f[l][mid][k]+f[mid+1][r][k]+1\)

\(g[l][r][k] = f[l][r][x]\) (x为任意不是k的数)

发现转移还挺对称的,呵呵,所以肯定是有优化方式的。

上面的方程每一句肯定都能看懂。但写转移方程的时候要注意一个顺序问题,要保证你对数列操作的每一个动作都要满足:操作前的状态比操作后的状态要先算出。

比如你改成先计算 g 再计算 f ,那么就有 f 的转移会多一句:\(f[l][r][k] = g[l][r][k]+1\),g 的最后一个转移反而就没必要了。

my submission

写区间dp,享调试人生。

这东西出bug挺难调的,希望以后让我涨rating的题不要再是区间dp了。

posted @ 2024-01-19 18:42  maple276  阅读(60)  评论(2)    收藏  举报