看上去像是个单调队列
怎么选出 min{f_j + [h_i >= h_j]} 呢
只要保证从 f 值最小的里面选出 h 最大的就好了
由于 h 带来的差异最多是 1,所以可以直接上单调队列
push 元素的时候比队尾优的条件就是 f[i] < f[tail] 或 (f[i] == f[tail] 且 h[i] >= h[tail])
代码:
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cctype>
#include <cstdio>
#include <queue>
using namespace std;
const int MAX_N = 1000005;
int n, m, k, hd, tl;
int h[MAX_N], f[MAX_N], q[MAX_N];
inline int rd() {
register int x = 0, c = getchar();
while (!isdigit(c)) c = getchar();
while (isdigit(c)) {
x = x * 10 + (c ^ 48);
c = getchar();
}
return x;
}
inline void dp() {
hd = 1; tl = 0;
f[1] = 0;
q[++tl] = 1;
for (int i = 2; i <= n; ++i) {
while (hd <= tl && i - q[hd] > k) ++hd;
f[i] = f[q[hd]] + (h[i] >= h[q[hd]]);
while (hd <= tl && ((f[q[tl]] > f[i]) || (f[q[tl]] == f[i] && h[i] >= h[q[tl]]))) --tl;
q[++tl] = i;
}
printf("%d\n", f[n]);
}
int main() {
n = rd();
for (int i = 1; i <= n; ++i) h[i] = rd();
m = rd();
while (m--) {
k = rd();
dp();
}
return 0;
}