CF1693D题解
很妙的dp题。
首先肯定要想判断一个序列是否合法。
第一篇题解的结论太强了,蒟蒻只能想到dp。
设 \(dp_{i,0}\) 表示 \(a_i\) 作为上升段末尾时,下降段末尾的最大值。
\(dp_{i,1}\) 表示 \(a_i\) 作为下降段末尾时,上升段末尾的最小值。
- 起点:\(dp_{i,0}=-inf,dp_{i,1}=inf(i>1),dp_{1,0}=inf,dp_{1,1}=-inf\)。
- 转移:
若 \(a_{i-1}\) 能接到上升段(即 \(dp_{i-1,0}\neq -inf\)),则 \(dp_{i,0} \leftarrow dp_{i-1,0}(a_i>a_{i-1}),dp_{i,1}\leftarrow a_{i-1}(a_i<dp_{i-1,0})\)。
若 \(a_{i-1}\) 能接到下降段(即 \(dp_{i-1,1}\neq inf\)),则 \(dp_{i,1} \leftarrow dp_{i-1,1}(a_i<a_{i-1}),dp_{i,0}\leftarrow a_{i-1}(a_i>dp_{i-1,1})\)。
那么暴力枚举子段,用上述 \(dp\) 即可做到 \(\mathcal{O}(n^3)\)。
考虑优化,假设固定左端点,那么合法的右端点只能是一个前缀,右端点右移的时候进行转移,优化为 \(\mathcal{O}(n^2)\)。
观察上面的 \(dp\) 转移,发现 \(dp_i\) 只与 \(dp_{i-1}\) 有关,如果 \(dp_{i-1}\) 在上一个左端点和当前左端点的值相同,\(i\) 后面的值都不会变化,那么我们从后往前枚举左端点,记录右端点的最大值 \(mxr\),如果发现某一处的 \(dp_i\) 未发生变化,直接继承上一次的 \(mxr\) 就行了,这样看似还是 \(\mathcal{O}(n^2)\),但这个做法足以通过本题。
有一个很神奇的性质:
对于所有左端点,\(dp_{i,0}\) 和 \(dp_{i,1}\) 都只有 \(4\) 种取值。
证明:
对于 \(i\),找到 \(i\) 之前最大的 \(j\) 满足 \(a_j>a_{j+1}\),那么 \(a_j\) 和 \(a_{j+1}\) 中必有一个是下降段的末尾,也就是说 \(dp_{i,0}=a_j/a_{j+1}/-inf\)。
如果不存在 \(j\),\(dp_{i,0}=inf\)。
对于 \(dp_{i,1}\) 同理。
于是每个点都最多被更新 \(7\) 次,之后就再也不会变化,复杂度降为 \(\mathcal{O}(n)\)。
浙公网安备 33010602011771号