Codeforces Round 892 (Div. 2)


\[\large \text{Round 7 : Codeforces Round 892 (Div. 2) (VP)} \]

一言:
所谓人,无论是谁到了最后,都会形单影只。
——悠久之翼2

最令人无语的是最后三分钟交代码的时候把 \(\text{D}\) 题交到了 \(\text{E}\) 题,结果能过的代码直接没有过。。

\(\text{D: Andrey and Escape from Capygrad}\)

这题乍一看每一个东西有四个要输入的,好像还挺复杂的,但仔细想想你就会发现,实际上只有 \(l_i,b_i\) 是有用的。(后面会讲为什么)

仔细想想,我们可以把 \([l_i,b_i]\) 当作一个区间,然后将所有有交集的区间合并在一起,最后输出的时候直接看 \(x\) 在那个区间里面,然后直接输出这个区间的右端点。

接下来我们仔细想想为什么。

首先可以发现,如果有一次传送是在向前面传送,那一定不是最优的(至少除去这些传送必然还会留下最优解)。可能你到了前面可以到达更大的 \(b_i\),但是这样的 \([l_i,r_i]\) 肯定是包含当前操作的这个点的,所以我们可以直接在这一次传送时向后面传送,不需要向前。

然后对于 \(b_i\) 右边那一部分,可以发现,它即使有可能处于 \([l_i,r_i]\) 这个区间里面,但他此时如果跳到 \(b_i\) 实际上是在往后面退的,可以保证这个一定不是最优解,对于 \([l_i,a_i]\) 这一部分,可以发现,他最多也只能到 \(b_i\),所以刚刚那个贪心策略就是对的了。

\(\text{Submission}\)

\(\text{E: Maximum Monogonosity}\)

首先我们可以想到一个 \(\text{DP}\),即 \(dp_{i,j}\) 表示前 \(i\) 个数,已经选了长度和为 \(j\) 的不相交的区间可以得到的价值总和的最大值。(假设 \(f_{l,r}\) 表示一个区间 \([l,r]\) 的价值,感觉这个状态也不是很好想啊)

可以考虑枚举一个 \(k\) 表示选了区间 \([i-k+1,i]\)(当然可以不选),那么显然有 \(\text{DP}\) 转移:\(dp_{i,j}=\max \{ dp_{i-k-1,j-k} + f_{i-k+1,i}\}\)

但是这样的时间复杂度是 \(O(n \times k ^2)\),显然不符合我们的要求。

可以发现,最难处理的是 \(f_{l,r}\) 的那两个绝对值。由于绝对值满足性质 \(|x| \in \{ x,-x\},|x| \ge \max\{x,-x\}\),所以我们可以把两个绝对值每个差一个正负号,合在一起就是 \(4\) 个,且可以发现只有合法的那个才有可能成为最大值。那么我们就可以重新写一次 \(\text{DP}\)

\[\begin{aligned} dp_{i,j}=\max \{ dp_{i-k,j-k} + a_i-b_{i-k+1}+b_i-a_{i-k+1}\} \\ dp_{i,j}=\max \{ dp_{i-k,j-k} - a_i+b_{i-k+1}+b_i-a_{i-k+1}\} \\ dp_{i,j}=\max \{ dp_{i-k,j-k} + a_i-b_{i-k+1}-b_i+a_{i-k+1}\}\\ dp_{i,j}=\max \{ dp_{i-k,j-k} - a_i+b_{i-k+1}-b_i+a_{i-k+1}\}\\ \end{aligned} \]

由于 \(a_i,b_i\) 是定值,整理一下就可以得到:

\[\begin{aligned} dp_{i,j}=\max \{ dp_{i-k,j-k} -b_{i-k+1}-a_{i-k+1}\}+a_i+b_i \\ dp_{i,j}=\max \{ dp_{i-k,j-k} +b_{i-k+1}-a_{i-k+1}\}-a_i+b_i \\ dp_{i,j}=\max \{ dp_{i-k,j-k} -b_{i-k+1}+a_{i-k+1}\}+a_i-b_i\\ dp_{i,j}=\max \{ dp_{i-k,j-k} +b_{i-k+1}+a_{i-k+1}\}-a_i-b_i\\ \end{aligned} \]

可以发现,对于中间那一坨最大值,他好像可以在求出 \(dp_{i-k,j-k}\) 的时候进行更新,可以发现 \(dp_{i-k,j-k},dp_{i,j}\) 的一个共同点就是他们的第一维坐标减去第二维坐标的差是一定的,所以我们可以定义一个 \(f_{x,0-3}\) 表示当前枚举到的所有的 \(i-j=x\)\(\max\) 里面那一坨的最大值。所以每次求 \(dp_{i,j}\) 时,就是 \(f_{i-j,0-3}\) 在加上 \(a_i,b_i\) 对应的贡献再求个最大值,且每次求完 \(dp_{i,j}\) 之后,要记得对对应的 \(f_{i-j,0-3}\) 进行更新。

\(\text{Submission}\)

\(\text{What I learned:}\)

  • 当你发现每个东西里面的一些相关条件有些是无关紧要的时候,可以考虑把他删去来降低题目的复杂程度。

  • 当出现绝对值的运算并且要求最值时,一定要想一想如果不考虑绝对值是否有可能让一些错误的值成为最值。如果否,那么你就可以直接把绝对值这东西删去了,这样更能方便推式子。

  • 当你优化 \(\text{DP}\) 的时间复杂度时,一定要思考一下当前状态与他之前的所有状态是否都有共同点(比如 \(dp_{i,j}\)\(dp_{i-k,j-k}\) 的共同点就是两维之差都是 \(i-j\)),且把转移式中只跟当前这个数相关的部分去掉,如果是,那么可以通过这个共同点维护一个东西(比如维护一个 \(f_x\) 维护此前所有 \(i-j=x\) 的所有状态最值),使得你能够快速找到是从哪个状态转移来是最优的,并且在求出一个 \(\text{DP}\) 式后,更新这个共同点维护的东西,从而优化复杂度。

posted @ 2024-03-04 15:14  Saltyfish6  阅读(2)  评论(0编辑  收藏  举报
Document