POI2014 PTA-Little Bird

题目传送门

比较简单的单调队列优化DP


转移方程很容易想到是 \(f_i = f_j + (a_i \geq a_j), j \geq i-k\)

直接暴力是\(O(n ^ 2)\)的,考虑单调队列优化
如果\(f_x < f_y\)\(f_x = f_y, a_x > a_y\),那么\(x\)一定不会比\(y\)差,我们只保留\(x\)就可以了

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define LL long long
LL read() {
    LL k = 0, f = 1; char c = getchar();
    while(c < '0' || c > '9') {
        if(c == '-') f = -1;
        c = getchar();
    }
    while(c >= '0' && c <= '9')
        k = k * 10 + c - 48, c = getchar();
    return k * f;
}
char read_c() {
    char c = getchar();
    while(c != 'M' && c != 'C') c = getchar();
    return c;
}
int a[1000010], q[1000010], h, t;
int f[1000010];
bool judge(int x, int y) {
    return f[x] > f[y] || (f[x] == f[y] && a[x] < a[y]);
}
int main() {
    int n = read();
    for(int i = 1; i <= n; ++i) a[i] = read();
    int m = read();
    while(m--) {
        int k = read(); h = 1, t = 0;
        q[++t] = 1; f[1] = 0;
        for(int i = 2; i <= n; ++i) {
            while(h <= t && q[h] < i - k) ++h;
            f[i] = f[q[h]] + (a[q[h]] <= a[i]);
            while(h <= t && judge(q[t], i)) --t;
            q[++t] = i;
        }
        printf("%d\n", f[n]);
    }

    return 0;
}
posted @ 2019-11-14 10:35  MorsLin  阅读(69)  评论(0编辑  收藏  举报