何为单调队列?
单调队列是一个队列(废话)
而且必须同时满足下标单调和值单调两个单调特性。
跟优先队列不同,优先队列直接使用堆(heap)来实现,如何删去特定下标元素?不明。
本人喜欢用单调队列存下标,这样比存值不知道高到哪里去了。
新来一个元素,进队。之后特判长度有没有超过。超过则把最前面的元素出队。
之后,如果不满足性质,就把前面的元素顶掉,直到满足性质为止。
然后才可以把队首元素拿来用。
有几个很坑的地方,具体看代码注释。
(为什么top是队尾而tail是队首?laughcry)
例题:洛谷P1886,高级模板题。还有一道剧毒的P2216。(排版很奇怪,都怪反人类的博客园☺)
AC代码:
1 #include <cstdio> 2 const int N = 1000010; 3 4 int pl[N], l_t, l_h = 1, ansl[N]; 5 int ps[N], s_t, s_h = 1, anss[N]; 6 int a[N]; 7 8 int main() { 9 int n, k; 10 scanf("%d%d", &n, &k); 11 for(int i = 1; i <= n; i++) { 12 scanf("%d", &a[i]); 13 } 14 for(int i = 1; i <= n; i++) { 15 pl[++l_t] = i; 16 ps[++s_t] = i; 17 if(pl[l_h] + k <= i) { 18 l_h++; 19 } 20 if(ps[s_h] + k <= i) { 21 s_h++; 22 } 23 while(l_t > l_h && a[pl[l_t - 1]] <= a[i]) { 24 l_t--; 25 } 26 while(s_t > s_h && a[ps[s_t - 1]] >= a[i]) { 27 s_t--; 28 } 29 pl[l_t] = i; 30 ps[s_t] = i; 31 ansl[i] = pl[l_h]; 32 anss[i] = ps[s_h]; 33 } 34 for(int i = k; i <= n; i++) { 35 printf("%d ", a[anss[i]]); 36 } 37 printf("\n"); 38 for(int i = k; i <= n; i++) { 39 printf("%d ", a[ansl[i]]); 40 } 41 return 0; 42 }