今天学习了下单调队列,在网上搜到一篇讲单调队列很不错的博客http://xuyemin520.is-programmer.com/posts/25964 ,单调队列顾名思义就是队列里的元素要单调,怎样维护单调性呢?以上述题目的要求为例。
1.首先看插入元素:为了保证队列的递减性,我们在插入元素v的时候,要将队尾的元素和待插入的val比较,如果队尾的元素不大于val,则删除队尾的元素,然后继续将新的队尾的元素与val比较,直到队尾的元素大于val,这个时候我们才将v插入到队尾。
2.那么队首的元素什么时候删除呢?由于我们只需要保存i的前k-1个元素中的最大值,所以当队首的元素的索引或下标小于 i-k+1的时候,就说明队首的元素对于求f(i)已经没有意义了,因为它已经不在窗里面了。所以当index[队首元素]<i-k+1时,将队首 元素删除。
下面是代码,用G++ TLE,C++才能过
#include <deque>
#include <queue>
#include <cstdio>
#define POB pop_back
#define PUB push_back
#define POF pop_front
using namespace std;
const int N = 1000010;
struct node{
int idx, val;
}num[N];
int main(){
int n, i, k;
while(~scanf("%d%d", &n, &k)){
queue<int> minQue, maxQue;
deque<node> down, up;
for(i = 1;i <= n;i++){
scanf("%d", &num[i].val);
num[i].idx = i;
}
for(i = 1;i <= k - 1;i++){
//单调递减
while(!down.empty()&&down.back().val < num[i].val)
down.POB();
down.PUB(num[i]);
//单调递增
while(!up.empty()&&up.back().val > num[i].val)
up.POB();
up.PUB(num[i]);
}
for(i = k;i <= n;i++){
/**维护递减单调队列**/
while(!down.empty()&&down.back().val < num[i].val)
down.POB();
down.PUB(num[i]);
while(!down.empty()&&down.front().idx < i - k + 1)
down.POF();
maxQue.push(down.front().val);
/**维护递增单调队列**/
while(!up.empty()&&up.back().val > num[i].val)
up.POB();
up.PUB(num[i]);
while(!up.empty()&&up.front().idx < i - k + 1)
up.POF();
minQue.push(up.front().val);
}
while(!minQue.empty()){
printf("%d ", minQue.front());
minQue.pop();
}
printf("\n");
while(!maxQue.empty()){
printf("%d ", maxQue.front());
maxQue.pop();
}
printf("\n");
}
return 0;
}