abc275_f Erase Subarrays 题解
Erase Subarrays
题意
有一个长度为
- 选择序列的一个子段,将子段中的每个数变为
。
对于 -1
。
数据范围
。 。
思路
一眼 dp,我用的是子序列 dp。
说是将序列子段的数变为
- 状态:
表示最后选取数了第 个数且数字和为 。- 数字和最大有
,总空间 ,MLE? - NO~,由于
最大只有 ,所以第二维也只要开到 即可。
- 数字和最大有
- 转移:两种情况分类讨论。
- 选择上一个数,即
。 - 不选上一个数,即
,因为上一个数不选,所以中间需要一次操作,需 。 - 取两种情况最小值即可。
- 一个小问题,第二中情况需要
查找,TLE,所以要用前缀最小值优化。
- 选择上一个数,即
- 初始状态:
,而对于 , 需赋值极大值(推荐使用 )。 - 目标状态(回答询问):
。- 假设当前回答的是第
组询问。 - 解释:如果没有选择最后一个数,那么序列的后缀必然需要一次操作,所以分开考虑。
- 假设当前回答的是第
复杂度
- 时间:
。 - 空间:
。
Code
点击查看代码
#include <bits/stdc++.h> using namespace std; const int N = 3e3 + 10; int n, x, m, dp[N][N], sum[N][N], ans; // sum 维护前缀最小值 int main () { ios::sync_with_stdio(0), cin.tie(0); cin >> n >> m; for (int i = 1; i <= m; i++) { // 赋值极大值 sum[0][i] = dp[0][i] = n; } for (int i = 1; i <= n; i++) { cin >> x; for (int j = 0; j < x; j++) { dp[i][j] = n; // 数字和小于 x 的没有意义,赋值极大值 } for (int j = x; j <= m; j++) { // 转移 dp[i][j] = dp[i - 1][j - x]; if (i >= 2) { dp[i][j] = min(dp[i][j], sum[i - 2][j - x] + 1); } } for (int j = 0; j <= m; j++) { sum[i][j] = min(sum[i - 1][j], dp[i][j]); // 随时维护前缀最小值 } } for (int i = 1; i <= m; i++) { // 处理询问 ans = n; for (int j = n; j; j--) { ans = min(ans, dp[j][i] + (j < n)); } cout << (ans < n ? ans : -1) << '\n'; } return 0; }
本文作者:wnsyou の blog
本文链接:https://www.cnblogs.com/wnsyou-blog/p/17447141.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步