您的位置:首页 > 其它

1126. Magnetic Storms(单调队列)

2013-03-09 22:13 337 查看
一开始扫描数组,时间复杂度O(n),然后找最大值用max_element,时间复杂度O(mlogm),总的时间复杂度O(nmlogm),直接TLE2,后来上网查到要用线段树或者单调队列才能过,学一下单调队列。
http://wenku.baidu.com/view/f88397a50029bd64783e2c5c.html一个挺好的单调队列的课件,有助于理解。
单调对列:单调队列是特殊的双端队列,元素是单调递减或者单调递增的,并且元素下标是单调递增的。

(单调队列需要两端删除,队尾插入)

常用操作:(1)插入:若新元素从队尾插入后会破坏单调性,则删除队尾元素,直到插入后不在破坏单调性,再将其插入单调队列。

(2)获取最大或最小值:访问队首元素。

维护方法:删除的时候,判断队首,如果队首元素下标小于当前段左边界就删除,不断删除队首直到队首元素下标大于等于当前段左边界。在每次插入的时候,先判断队尾元素,如果不比待插入元素大就删除,不断删除队尾直到队尾元素大于待插入元素或者队空。此时直接输出队首元素就行了。 

用stl做可以省去开大数组的空间:

#include <cstdio>
#include <deque>
using namespace std;
struct Node
{
int value, index;
};                        //存储每个元素的数值和下标
int main()
{
int m;
scanf("%d", &m);
Node node;
deque<Node> dqN;
int num = 0;
while (scanf("%d", &node.value) && node.value != -1)
{
node.index = num++;
while (!dqN.empty() && dqN.front().index < num - m)
dqN.pop_front();
while (!dqN.empty() && dqN.back().value < node.value)
dqN.pop_back();
dqN.push_back(node);
if (num >= m)                                         //超出限定的m输出队首元素
printf("%d\n", dqN.front().value);
}
system("pause");
return 0;
}


用数组模拟(需要开两个数组):

#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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: