http://acm.cs.ecnu.edu.cn/problem.php?problemid=2450
用单调队列 queue[] 维护一个可能作为最大值的序列,
由贪心策略,这个序列是单调减的。
扫描到元素 a[i] 时, 这个序列满足:
1.始终保持队首元素是[i-k+1, i-1]的最大值。
(即 如果队首不在当前区间[i-k+1, i]中,则出队)
2.队中其余元素则是将来队首出队后可能的最大值。
综上,该算法是 O(n)的, 比 线段树 要快呢。
参考链接:
http://wenku.baidu.com/view/4d23b4d128ea81c758f578ae.html
1 #include <iostream> 2 #include <stdio.h> 3 #include <string> 4 #include <algorithm> 5 #include <string.h> 6 #include <stdlib.h> 7 #define MAXN 100000 8 #define INF 0x3f3f3f3f 9 using namespace std; 10 11 struct P{ 12 int v, id; 13 }q[MAXN+5]; 14 int head, tail; 15 16 void enqueue(int v, int id){ 17 q[++tail].v = v; 18 q[tail].id = id; 19 } 20 21 int main() 22 { 23 int t; 24 cin >> t; 25 while(t--){ 26 head=-1, tail=-1; 27 int n, k, x; 28 cin >> n >> k; 29 for(int i=0; i<k; i++){ 30 scanf("%d", &x); 31 while(x >= q[tail].v && head < tail) 32 tail --; 33 enqueue(x, i); 34 } 35 printf("%d", q[head+1].v); 36 for(int i=k; i<n; i++){ 37 scanf("%d", &x); 38 if(q[head+1].id < i-k+1) 39 head ++; 40 if(head == tail){ 41 printf(" %d", x); 42 enqueue(x, i); 43 } 44 else{ 45 printf(" %d", max(x, q[head+1].v)); 46 while(x >= q[tail].v && head < tail) 47 tail --; 48 enqueue(x, i); 49 } 50 } 51 printf(" "); 52 } 53 54 return 0; 55 }