[COCI2022-2023#5] Slastičarnica 题解
前言
题目链接:洛谷。
题意简述
一个长为
题目分析
转移其实就是进行某一次操作。找到一对使
其中,区间最小值可以在转移的时候用单调队列维护,但是没必要,
遇到记录的是布尔值的 DP,往往有两种思考方向:使用 bitset
压位转移;考虑贪心后记录状态的最值。前者显然不适用本题,解释一下后者。对于具有相同左端点的区间
优化后,状态数由
- 当前使用前缀。
- 当前使用后缀。
朴素转移的话,时间是
于是时间可以优化至
代码
展开 代码
#include <cstdio> #include <iostream> #include <cstring> using namespace std; const int N = 5010; int n, q, a[N], _ = 1; int mi[N][N]; bool f[N][N], g[N][N]; signed main() { scanf("%d%d", &n, &q), q > n && (q = n); for (int i = 1; i <= n; ++i) scanf("%d", &a[i]), mi[i][i] = a[i]; for (int l = 1; l <= n; ++l) for (int r = l + 1; r <= n; ++r) mi[l][r] = min(mi[l][r - 1], a[r]); f[1][n] = true; for (int sum = 0, d, s; _ <= q; ++_) { scanf("%d%d", &d, &s), sum += d; if (sum > n) break; memcpy(g, f, sizeof(f)); memset(f, 0x00, sizeof(f)); bool ok = false; for (int l = 1; l <= n; ++l) for (int r = l + d - 1; r <= n; ++r) if (g[l][r]) { for (int k = l; k + d - 1 <= r; ++k) if (mi[k][k + d - 1] >= s) { f[k + d][r] = true; ok = true; break; } for (int k = r; k - d + 1 >= l; --k) if (mi[k - d + 1][k] >= s) { f[l][k - d] = true; ok = true; break; } } if (!ok) break; } printf("%d", _ - 1); return 0; }
展开 代码
#include <cstdio> #include <iostream> #include <cstring> using namespace std; const int N = 5010; int n, q, a[N], _ = 1; int mi[N][N]; int f[N], g[N]; signed main() { scanf("%d%d", &n, &q), q > n && (q = n); for (int i = 1; i <= n; ++i) scanf("%d", &a[i]), mi[i][i] = a[i]; for (int l = 1; l <= n; ++l) for (int r = l + 1; r <= n; ++r) mi[l][r] = min(mi[l][r - 1], a[r]); f[1] = n; for (int sum = 0, d, s; _ <= q; ++_) { scanf("%d%d", &d, &s), sum += d; if (sum > n) break; memcpy(g, f, sizeof(f)); memset(f, -0x3f, sizeof(f)); for (int l = 1; l <= n; ++l) { for (int r = l; r <= g[l] - d; ++r) if (mi[r + 1][r + d] >= s) f[l] = max(f[l], r); if (l - d >= 1 && mi[l - d][l - 1] >= s) for (int k = 1; k <= l - d; ++k) f[l] = max(f[l], g[k]); } bool ok = false; for (int i = 1; i <= n && !ok; ++i) ok |= f[i] >= i - 1; if (!ok) break; } printf("%d", _ - 1); return 0; }
展开 代码
#include <cstdio> #include <iostream> #include <cstring> using namespace std; const int N = 5010; int n, q, a[N], _ = 1, mi[N][N]; int f[N], g[N], p[N], h[N]; signed main() { scanf("%d%d", &n, &q), q > n && (q = n); for (int i = 1; i <= n; ++i) scanf("%d", &a[i]), mi[i][i] = a[i]; for (int l = 1; l <= n; ++l) for (int r = l + 1; r <= n; ++r) mi[l][r] = min(mi[l][r - 1], a[r]); f[1] = n; for (int sum = 0, d, s; _ <= q; ++_) { scanf("%d%d", &d, &s), sum += d; if (sum > n) break; memcpy(g, f, sizeof(f)); for (int i = 1, c = 0; i <= n; ++i) { p[i] = max(p[i - 1], g[i]); a[i] >= s ? ++c : c = 0; h[i] = c >= d ? i - d : h[i - 1]; } for (int l = 1; l <= n; ++l) { f[l] = -0x3f3f3f3f; if (g[l] >= l && h[g[l]] >= l) f[l] = max(f[l], h[g[l]]); if (l - d >= 1 && mi[l - d][l - 1] >= s) f[l] = max(f[l], p[l - d]); } bool ok = false; for (int i = 1; i <= n && !ok; ++i) ok |= f[i] >= i - 1; if (!ok) break; } printf("%d", _ - 1); return 0; }
展开优化常数后 代码
#include <cstdio> const int N = 5010; int n, q, a[N], _ = 1; int f[N], p[N], h[N]; inline void tomax(int &a, int &b) { b > a && (a = b); } signed main() { scanf("%d%d", &n, &q), q > n && (q = n), f[1] = n; for (int i = 1; i <= n; ++i) scanf("%d", &a[i]); for (int sum = 0, d, s; _ <= q; ++_) { scanf("%d%d", &d, &s), sum += d; if (sum > n) break; for (int i = 1, c = 0; i <= n; ++i) { p[i] = f[i] > p[i - 1] ? f[i] : p[i - 1]; a[i] >= s ? ++c : c = 0; h[i] = c >= d ? i - d : h[i - 1]; } bool ok = false; for (int l = 1, c = 0; l <= n; ++l) { int g = -0x3f3f3f3f; if (f[l] >= l && h[f[l]] >= l) tomax(g, h[f[l]]); if (c >= d) tomax(g, p[l - d]); a[l] >= s ? ++c : c = 0; f[l] = g, ok |= g >= l - 1; } if (!ok) break; } printf("%d", _ - 1); return 0; }
本文作者:XuYueming,转载请注明原文链接:https://www.cnblogs.com/XuYueming/p/18536522。
若未作特殊说明,本作品采用 知识共享署名-非商业性使用 4.0 国际许可协议 进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!