18.12.16 滑動窗口(單調隊列)

描述

給定一個長度爲n(n<=10^6)的數組。有一個大小爲k的滑動窗口從數組的最左端移動到最右端。你能夠看到窗口中的k個數字。窗口每次向右滑動一個數字的距離。
下面是一個例子:
數組是 [1 3 -1 -3 5 3 6 7], k = 3。

窗口位置 最小值 最大值
[1  3  -1] -3  5  3  6  7  -1 3
 1 [3  -1  -3] 5  3  6  7  -3 3
 1  3 [-1  -3  5] 3  6  7  -3 5
 1  3  -1 [-3  5  3] 6  7  -3 5
 1  3  -1  -3 [5  3  6] 7  3 6
 1  3  -1  -3  5 [3  6  7] 3 7


你的任務是獲得滑動窗口在每一個位置時的最大值和最小值。

 

輸入

輸入包括兩行。
第一行包括n和k,分別表示數組的長度和窗口的大小。
第二行包括n個數字。輸出輸出包括兩行。
第一行包括窗口從左至右移動的每一個位置的最小值。
第二行包括窗口從左至右移動的每一個位置的最大值。node

樣例輸入

8 3 1 3 -1 -3 5 3 6 7

樣例輸出

-1 -3 -3 -3 3 3 3 3 5 5 6 7ios

 1 #include <iostream>
 2 #include <string.h>
 3 #include <algorithm>
 4 #include <stack>
 5 #include <string>
 6 #include <math.h>
 7 #include <queue>
 8 #include <stdio.h>
 9 #include <string.h>
10 #include <vector>
11 #include <fstream>
12 #define maxn 1000005
13 #define inf 999999
14 #define cha 127
15 using namespace std; 16 
17 struct node { 18     int p, val; 19     node(int a, int b) { 20         p = a, val = b; 21  } 22 }; 23 deque<node>minq; 24 deque<node>maxq; 25 int n, k; 26 int imin, imax; 27 
28 void insert(node val,int first) { 29     
30     while (!minq.empty() &&minq.back().val >= val.val) 31  minq.pop_back(); 32  minq.push_back(val); 33     while ( minq.front().p < first) 34  minq.pop_front(); 35     while (!maxq.empty() &&maxq.back().val <= val.val) 36  maxq.pop_back(); 37  maxq.push_back(val); 38     while ( maxq.front().p < first) 39  maxq.pop_front(); 40 } 41 
42 int minans[maxn], maxans[maxn]; 43 void init() { 44     scanf("%d%d", &n, &k); 45     int tmp; 46     for (int i = 1; i <= k - 1; i++) { 47         scanf("%d", &tmp); 48         insert(node(i, tmp),1); 49  } 50     for (int i = k; i <= n; i++) { 51         int l = i - k + 1; 52         scanf("%d", &tmp); 53  insert(node(i, tmp), l); 54         minans[++imin] = minq.front().val; 55         maxans[++imax] = maxq.front().val; 56  } 57     printf("%d", minans[1]); 58     for (int i = 2; i <= imin; i++) 59         printf(" %d", minans[i]); 60     printf("\n"); 61     printf("%d", maxans[1]); 62     for (int i = 2; i <= imax; i++) 63         printf(" %d", maxans[i]); 64     printf("\n"); 65 } 66 
67 int main() 68 { 69  init(); 70     return 0; 71 }
View Code

上面是1k4ms樣子過的,但我就很奇怪我寫的另外一個類似版本tle:數組

 1 #include <iostream>
 2 #include <string.h>
 3 #include <algorithm>
 4 #include <stack>
 5 #include <string>
 6 #include <math.h>
 7 #include <queue>
 8 #include <stdio.h>
 9 #include <string.h>
10 #include <vector>
11 #include <fstream>
12 #define maxn 1000005
13 #define inf 999999
14 #define cha 127
15 using namespace std; 16 
17 struct node { 18     int p, val; 19     node(int a, int b) { 20         p = a, val = b; 21  } 22 }; 23 deque<node>minq; 24 deque<node>maxq; 25 int n, k; 26 int imin, imax; 27 
28 void insert(node val,int first) { 29     while (!minq.empty() && minq.front().p < first) 30  minq.pop_front(); 31     while (!maxq.empty() && maxq.front().p < first) 32  maxq.pop_front(); 33     for (int i = minq.size() - 1; i >= 0; i--) { 34         if (minq[i].val >= val.val) 35  minq.pop_back(); 36  } 37  minq.push_back(val); 38     for (int i = maxq.size() - 1; i >= 0; i--) { 39         if (maxq[i].val <= val.val) 40  maxq.pop_back(); 41  } 42  maxq.push_back(val); 43 } 44 
45 int minans[maxn], maxans[maxn]; 46 void init() { 47     scanf("%d%d", &n, &k); 48     int tmp; 49     for (int i = 1; i <= k - 1; i++) { 50         scanf("%d", &tmp); 51         insert(node(i, tmp),1); 52  } 53     for (int i = k; i <= n; i++) { 54         int l = i - k + 1; 55         scanf("%d", &tmp); 56  insert(node(i, tmp), l); 57         minans[++imin] = minq.front().val; 58         maxans[++imax] = maxq.front().val; 59  } 60     printf("%d", minans[1]); 61     for (int i = 2; i <= imin; i++) 62         printf(" %d", minans[i]); 63     printf("\n"); 64     printf("%d", maxans[1]); 65     for (int i = 2; i <= imax; i++) 66         printf(" %d", maxans[i]); 67     printf("\n"); 68 } 69 
70 int main() 71 { 72  init(); 73     return 0; 74 }
View Code

感受也沒調用什麼……順序改變了一下。我發現我寫的程序都好慢啊……寫lab的時候就體會到了,個人程序老是跑很慢|||ide

單調隊列

用deque比較容易實現性能

維護區間最值spa

主要操做是每次加入新值刪除隊頭冗餘值,而且刪去隊尾全部比新值小的值,使得整個隊老是單調code

性能是O(n)blog

那麼問題來了,一個沒有競勝過的菜雞怎麼在考試的時候知道這些??隊列

相關文章
相關標籤/搜索