【洛谷P3800】Power收集(DP+单调队列)

题目链接:https://www.luogu.com.cn/problem/P3800

刷了一点板子题。

暴力DP很好想,然后发现是一个【滑动窗口】模型。

单调队列优化。

完。

#include <iostream>
#include <cstdio>
#include <cstring>
#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;
}

猜你喜欢

转载自www.cnblogs.com/blog-fgy/p/12408887.html