2024.11.3训练记录

杂题选讲

CF1392F Omkar and Landslide

手玩会发现,最后的序列必定要么全都差 \(1\) 上升,要么有一个位置与上一个相同,其他位置仍然差 \(1\) 上升。

那么在 \([1, i - 1]\) 合法的情况下:

\([1, i - 1]\) 中没有相同项,会增加一个相同项。
\([1, i - 1]\) 中存在相同项,会减少一个相同项或者维持数量不变。

所以相同项的数量一定是 \(0\)\(1\)

那么可以先将最终的答案刻画为升序的形式,最后再考虑相同位的影响。

设升序时序列的第一项为 \(x\),原序列总和为 \(s\)

\(s = \dfrac{n(x + x + n - 1)}{2}\)

对于没有相同项的情况这里解出来 \(x\) 就可以直接过了。

有相同项的情况,数列是:\(x, x+1, x+2, ..., x+i, x+i, ..., x + n - 2\)
于是上取整解出来 \(x\),按照和与 \(s\) 的差解出来 \(i\) 就能过了。

这题主要还是要发现性质,考场做的时候自己写一个大一点的样例。应该就容易推出来。

[JOISC2022] 复制粘贴 3

数据范围:\(n \leq 2500\)
所以考虑区间dp。

\(f[i][j]\) 表示用三种操作写出区间 \([i, j]\) 的最小代价。

首先有 \(f[i][j] = min(f[i + 1][j], f[i][j - 1]) + A\)

然后考虑如何做 \(2\)\(3\) 操作。
考虑在已经得到 $f[i][j] $后,将 \([i, j]\) 区间剪切,用来刷表。
因为我们会做第一种转移,所以 \(2\)\(3\) 操作只需要考虑两头都是剪贴板上东西的区间。
所以做刷表的时候需要找到 \([i, j]\) 后的每一个与 \([i, j]\) 相同的区间 \([k, l]\),刷新 \(f[i][l]\) 的答案。

\(cnt\)\([i, l]\) 中与 \([i, j]\) 相同的区间个数。则:
\(f[i][l] = min(f[i][l], f[i][j] + B + C * cnt + A * (len(i, l) - cnt * len(i, j))\)
这里有贪心思想。既然剪切后粘贴一次会更优,那么这个区间内所有一样的区间都会用粘贴来写出。

现在问题来到怎么求出上式中的 \(cnt\)
我们可以求出一个 \(nxt[i][L]\) 表示 $[i, i + L - 1] $后下一个与 \([i, i + L - 1]\) 相同的区间的左端点。
这只要枚举两个区间的端点 \(i\)\(j\),就可以二分求出满足 \([i, i + L - 1]\) 等于 \([j, j + L - 1]\) 最大的 \(L\)。(\(i + L - 1 < j\)
这样就可以用 \(j\) 来更新 \(nxt[i][L]\),最后对于每个 \(i\) 做一遍后缀最小值就可以成功预处理出 \(nxt\) 数组。

求出 \(nxt\) 后,我们在转移时可以直接遍历每一个 \(cnt\)
由于每个区间不相交,所以复杂度是调和级数,所以总的转移复杂度是 \(O(n^2 \log n)\)

这题的特点还是在相等的区间转移的写法,其他题也可以借鉴。
我写的有点奇怪了,应该可以纯刷表。

posted @ 2024-11-03 20:44  docx君  阅读(5)  评论(0编辑  收藏  举报