【洛谷P3800】Power收集(DP+单调队列)
题目链接:https://www.luogu.com.cn/problem/P3800
刷了一点板子题。
暴力DP很好想,然后发现是一个【滑动窗口】模型。
单调队列优化。
完。
#include#include #include #define Re register using namespace std; const int maxN = 4005; int N, M, K, T, val[maxN][maxN], f[maxN][maxN], g[maxN]; int head, tail, q[maxN << 1]; int main() { cin >> N >> M >> K >> T; for (Re int i = 1; i <= K; ++i) { Re int x, y, z; scanf("%d%d%d", &x, &y, &z); val[x][y] = z; } memset(f, -0x3f, sizeof(f)); for (int i = 1; i <= M; ++i) f[1][i] = val[1][i]; tail = 0, head = 1; for (Re int i = 2; i <= N; ++i) { q[head = 0] = q[tail = 1] = 0; for (Re int j = 1; j <= M; ++j) { while (head <= tail && j - q[head] + 1 > T + 1) ++head; while (head <= tail && f[i - 1][q[tail]] <= f[i - 1][j]) --tail; q[++tail] = j, g[j] = f[i - 1][q[head]]; } for (Re int j = 1; j <= M; ++j) { Re int l = j, r = min(j + T, M); f[i][j] = max(g[l], g[r]) + val[i][j]; } } int Ans = -2e9; for (int i = 1; i <= M; ++i) Ans = max(Ans, f[N][i]); printf("%d\n", Ans); return 0; }