EOJ 2450 sunny的队列

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 }
View Code
原文地址:https://www.cnblogs.com/KimKyeYu/p/3307839.html