[luoguP3572] [POI2014]PTA-Little Bird(DP + 单调队列)

传送门

 

DP方程

f[i] = f[j] + (a[j] <= a[i])  ( i - k < j < i )

要使 f[i] 最小,需要等号后面的值最小,可以用单调队列来维护。

至于如何维护,具体看代码。

 

——代码

 1 #include <cstdio>
 2 
 3 const int MAXN = 1000005;
 4 int n, k, Q, h, t;
 5 int a[MAXN], q[MAXN], f[MAXN];
 6 
 7 inline bool cmp(int x, int y)
 8 {
 9     return f[x] > f[y] || (f[x] == f[y] && a[x] < a[y]);
10 }
11 
12 int main()
13 {
14     int i;
15     scanf("%d", &n);
16     for(i = 1; i <= n; i++) scanf("%d", &a[i]);
17     scanf("%d", &Q);
18     while(Q--)
19     {
20         scanf("%d", &k);
21         f[q[1] = h = t = 1] = 0;
22         for(i = 2; i <= n; i++)
23         {
24             while(h <= t && q[h] < i - k) h++;
25             f[i] = f[q[h]] + (a[q[h]] <= a[i]);
26             while(h <= t && cmp(q[t], i)) t--;
27             q[++t] = i;
28         }
29         printf("%d\n", f[n]);
30     }
31     return 0;
32 }
View Code

 

总结

这个题告诉我们,单调队列的单调性不仅仅只是个 < 或 > ,单调性是要满足最优解在一定在最前面。

posted @ 2017-05-11 11:45  zht467  阅读(118)  评论(0编辑  收藏  举报