一開始掃描數組,時間複雜度O(n),然後找最大值用max_element,時間複雜度O(mlogm),總的時間複雜度O(nmlogm),直接TLE2,後來上網查到要用線段樹或者單調隊列才能過,學一下單調隊列。
http://wenku.baidu.com/view/f88397a50029bd64783e2c5c.html一個挺好的單調隊列的課件,有助於理解。
單調對列:單調隊列是特殊的雙端隊列,元素是單調遞減或者單調遞增的,並且元素下標是單調遞增的。
(單調隊列需要兩端刪除,隊尾插入)
常用操作:(1)插入:若新元素從隊尾插入後會破壞單調性,則刪除隊尾元素,直到插入後不在破壞單調性,再將其插入單調隊列。
(2)擷取最大或最小值:訪問隊首元素。
維護方法:刪除的時候,判斷隊首,如果隊首元素下標小於當前段左邊界就刪除,不斷刪除隊首直到隊首元素下標大於等於當前段左邊界。在每次插入的時候,先判斷隊尾元素,如果不比待插入元素大就刪除,不斷刪除隊尾直到隊尾元素大於待插入元素或者隊空。此時直接輸出隊首元素就行了。
用stl做可以省去開大數組的空間:
1 #include <cstdio> 2 #include <deque> 3 using namespace std; 4 struct Node 5 { 6 int value, index; 7 }; //儲存每個元素的數值和下標 8 int main() 9 {10 int m;11 scanf("%d", &m);12 Node node;13 deque<Node> dqN;14 int num = 0;15 while (scanf("%d", &node.value) && node.value != -1)16 {17 node.index = num++;18 while (!dqN.empty() && dqN.front().index < num - m) 19 dqN.pop_front();20 while (!dqN.empty() && dqN.back().value < node.value)21 dqN.pop_back();22 dqN.push_back(node);23 if (num >= m) //超出限定的m輸出隊首元素24 printf("%d\n", dqN.front().value);25 }26 // system("pause");27 return 0;28 }
用數組類比(需要開兩個數組):
#include <cstdio>#include <iostream>int main(){ int ele[250001] = {0}, index[250001] = {0}; int m; scanf("%d", &m); int front = 1, back = 1; //類比隊首隊尾指標 for (int i = 1; ; ++i) { int t; scanf("%d", &t); if (t == -1) return 0; while (front <= back && i - index[front] >= m) ++front; while (back >= front && ele[back] < t) --back; ele[++back] = t; index[back] = i; if (i >= m) printf("%d\n", ele[front]); } system("pause"); return 0;}