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;
}