BZOJ3831: [Poi2014]Little Bird
看上去像是个单调队列
怎么选出 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; }
禁止诸如开发者知识库/布布扣/码迷/学步园/马开东等 copy 他人博文乃至博客的网站转载
,用户转载请注明出处:https://www.cnblogs.com/xcysblog/