Codeforces Round 892 (Div. 2) 复盘

A没啥好说的。B也是,很简单的贪心。 但是AB都因为读题导致的理解误差wa了一发。哎,读题读错,只能说英语还得练。

C,赛时没做出来,后面的也是。

这个题目其实思路已经有了,cf的这种题,还放在C题,那就是很明显那种能打标看出规律的东西。 就算知道了是打表能看出来的,我懒得写暴力,所以就一直在手推尝试找到规律。 但是失败了,浪费了大量时间。事实上枚举全排列就直接用next_permutation,格式和sort一样。 哎,写暴力也要果决一些。

D的话,其实是很简单的。1800的题目,难不到哪里去。 有一个并查集的理解可能需要加深,然后这种类型刚刚好戳到了盲点。 这个区间覆盖的问题不够熟悉,这种维护并查集是可以直接O(n)做的,是正正好好的并查集模板 思考的也不够冷静,其实总结一下特点就知道排序的要求了,就是很基本的从难到容易的思路。

过一天补的。 完全没必要并查集,直接按照区间左端点排序然后合并就可以了,我有些地方被弄混了,白写一份代码。 很痛苦嗷。 然后二分查找就可以了,这样写的代码很短,而且好想,而且好调,而且快。 现在看来思路是真的很清晰,但是我第一次写的时候很不清晰。主要就是因为这个区间跳跃的操作简化不够。事实上给的4个数字真正有用的只有两个。这个想清楚,后面合并的时候就很清晰。 再就是二分查找也好些很多了。

唉,这题完全可以做出来,一点不难的。太可惜了。

E的话一眼dp,然后观察一下方程,f[i][j]表示前i个位置已经选了长度为j的区间,且第i个位置已经被选上时,能够获得的最大值

$$
f[i][j]=\displaystyle\max_{1\leq k\leq min(i,j)}(f[i-k][j-k]+calc(i-k+1,j))\\ calc(l,r)=|b_l-a_r|+|b_r-a_l|
$$

这样的dp是O(n^2k)的,而1\leq k\leq n\leq 3000,我们需要优化到O(n^2log(n))这个级别。

观察dp,考虑优化,正常情况下,优化的部分都是枚举k的部分,我们对每次转移分开考虑,假如我不需要再去枚举k,而是直接通过数据结构查询得到就可以了。

发现f[i-k][j-k]是一个很有规律的东西,转化为图形,就是在dp数值组成的表里面斜率为1的直线通过的点。而这个很明显是可以维护的,问题就在后面的calc的代价函数中

我们现在的f[i-k][j-k]可以被单独维护,导致我们必须枚举k的东西是calc中含有k的部分,假如这部分不存在,那么其实直接维护f[i-k][j-k]和后面剩下部分的max即可,对于绝对值也是随便处理,因为这个值其实是固定的。 而含有和k相关的部分,这导致先前使用过的,已经维护好的f[i-k][j-k]的最大值并不能直接套用,我们必须考虑新的一位和前面部分的结合而形成的绝对值的影响。

假如把绝对值去掉,是否能做呢? 可以。而且很好做。观察发现,其实calc函数中含有k的部分是和f[i-k][j-k]绑定的,这个其实从题目中对价值的描述中可以更好的看出来。也就是说,我们其实是直接维护了这个式子含有k的所有部分一同的最大值,这个很好,因为剩下的只和i,j相关的部分的值是确定的,也就是说我们需要的东西就直接O(1)维护好了。 而这个只是没有绝对值的情况,绝对值这个东西也不算难处理,直接分类讨论,拆开,我们两个绝对值一共4中情况,用4个二维偏序直接维护就可以了。

不错的dp,分析这个代价函数的内容是情理之中,而这个代价函数中和f[i-k][j-k]强相关的部分是要从题目中理解得到的,这算是一个小难点。其实拆开绝对值的操作也是很合理的,想要优化这个dp,无非就是从状态和转移两方面下手,所有的dp都是这么优化的,而状态的优化其实是对应了前两个循环,这很显然很难办到,那就是加速转移。想要加速转移,那拆开这个绝对值就是必要的思路。 这边就给我提供了一个很好的思路,先假设绝对值不存在,这个事实上也是一个存在的情况。

还算简单的一个dp优化吧。这题居然能有2500。那9062E2居然只有2600。这两题之间的难度差距真心挺大。



posted @ 2024-04-23 19:25  HL_ZZP  阅读(6)  评论(0编辑  收藏  举报