18.12.16 滑動視窗(單調佇列)
阿新 • • 發佈:2018-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個數字。輸出輸出包括兩行。
第一行包括視窗從左至右移動的每個位置的最小值。
第二行包括視窗從左至右移動的每個位置的最大值。
樣例輸入
8 3
1 3 -1 -3 5 3 6 7
樣例輸出
-1 -3 -3 -3 3 3 3 3 5 5 6 7
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的時候就體會到了,我的程式總是跑很慢|||
單調佇列
用deque比較容易實現
維護區間最值
主要操作是每次加入新值刪除隊頭冗餘值,並且刪去隊尾所有比新值小的值,使得整個隊總是單調
效能是O(n)
那麼問題來了,一個沒有競賽過的菜雞怎麼在考試的時候知道這些??