| Time Limit: 12000MS | Memory Limit: 65536K | |
| Total Submissions: 38520 | Accepted: 11415 | |
| Case Time Limit: 5000MS | ||
Description
| Window position | Minimum value | Maximum value |
|---|---|---|
| [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 |
Your task is to determine the maximum and minimum values in the sliding window at each position.
Input
Output
Sample Input
8 3 1 3 -1 -3 5 3 6 7
Sample Output
-1 -3 -3 -3 3 3 3 3 5 5 6 7
一道裸的单调队列,求区间最值问题。线段树8秒多过,单调队列4秒多过。可作为单调队列的学习题目。
先说一下单调队列是一种什么样的队列。单调队列分为递增和递减队列,下面以递增队列为例:
1.该队列时刻保持队头元素最小且递增。元素从队尾插入,如果小于队尾元素,那么就删去队尾元素,再插入。
2.同时需要一个数组保存元素下标,以本题为例,区间长度为k,队头元素的下标小于当前元素下标i-k+1时,也就是此时队头元素已经不在k区间内了,就把队头元素删去。
#include<iostream>
#include<cstdio>
#define M 1000001
using namespace std;
int n,k;
int a[M];
int q[M];
int p[M];
void get_min()
{
int head=1;
int tail=0;
for(int i=0;i<k-1;i++)
{
while(head<=tail&&a[i]<=q[tail])
--tail;
q[++tail]=a[i];
p[tail]=i;
}
for(int i=k-1;i<n;i++)
{
while(head<=tail&&a[i]<=q[tail])
--tail;
q[++tail]=a[i];
p[tail]=i;
while(p[head]<i-k+1)
{
++head;
}
cout<<q[head]<<" ";
}
cout<<endl;
}
void get_max()
{
int head=1;
int tail=0;
for(int i=0;i<k-1;i++)
{
while(head<=tail&&a[i]>=q[tail])
--tail;
q[++tail]=a[i];
p[tail]=i;
}
for(int i=k-1;i<n;i++)
{
while(head<=tail&&a[i]>=q[tail])
--tail;
q[++tail]=a[i];
p[tail]=i;
while(p[head]<i-k+1)
{
++head;
}
cout<<q[head]<<" ";
}
cout<<endl;
}
int main()
{
//freopen("d:\\test.txt","r",stdin);
scanf("%d%d",&n,&k);
for(int i=0;i<n;i++)
{
scanf("%d",&a[i]);
}
get_min();
get_max();
return 0;
}
原文地址:http://blog.csdn.net/u012198382/article/details/38377903