双端队列(单调队列)poj2823 区间最小值(RMQ也可以)
Sliding Window
Time Limit: 12000MS | Memory Limit: 65536K | |
Total Submissions: 41844 | Accepted: 12384 | |
Case Time Limit: 5000MS |
Description
An array of size n ≤ 106 is given to you. There is a sliding window of size k which is moving from the very left of the array to the very right. You can only see the k numbers in the window. Each time the sliding window moves rightwards by one position. Following is an example:
The array is [1 3 -1 -3 5 3 6 7], and k is 3.
The array is [1 3 -1 -3 5 3 6 7], and k is 3.
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
The input consists of two lines. The first line contains two integers n and k which are the lengths of the array and the sliding window. There are n integers in the second line.
Output
There are two lines in the output. The first line gives the minimum values in the window at each position, from left to right, respectively. The second line gives the maximum values.
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
双端队列介绍:
deque和vector一样都是标准模板库中的内容,deque是双端队列,在接口上和vector非常相似,在许多操作的地方可以直接替换。假如读者已经能够有效地使用vector容器,下面提供deque的成员函数和操作,进行对比参考。
deque<type>q;
q.empty():判断队列是否为空
q.front() ,q.back() 队列的首元素和尾元素
q.begin() ,q.end() 返回队列首元素和结尾地址
q.push_front() ,q.push_back() 分别在队首和队尾插入元素
q.pop_front() ,q.pop_back() 删除首元素和尾元素
q.size() 返回容器中元素的个数
q.clear() 清空所有元素
本题最好采用模拟队列,缩短时限,分析怎样维护递增单调队列,开一个结构体要有id序号,和v值两个内容,首先当队列为空的时候,加入第一个元素;对于下一个将要加入的元素,把该元素a的大小和队尾的元素大小tail进行比较,如果a>tail,则移除尾元素,继续比较,直到a<=tail时把a加入到队列的尾部,当k个连续的数列向后移动时,队列中的前面的元素可能已经不再此范围内了,所以还要判断首元素的序号是不是在此时的范围内,如果不在,这删除首元素(即head++)直到满足条件为止,这样便可以维护一个单调递增队列
当维护单调递减序列的道理同上
程序:
#include"cstdio" #include"cstring" #include"cstdlib" #include"cmath" #include"string" #include"map" #include"cstring" #include"algorithm" #include"iostream" #include"set" #include"queue" #include"stack" #define inf 1000000000000 #define M 1000009 #define LL long long #define eps 1e-12 #define mod 1000000007 #define PI acos(-1.0) using namespace std; int a[M],maxi[M],mini[M]; struct node { int v,id; node(){} node(int id,int v) { this->v=v; this->id=id; } }qmin[M*2],qmax[M*2]; int main() { int n,k; while(scanf("%d%d",&n,&k)!=-1) { int minhead=0,mintail=0; int maxhead=0,maxtail=0; int cnt=0; for(int i=1;i<=n;i++) { scanf("%d",&a[i]); if(i<=k) { while(mintail>minhead&&a[i]<qmin[mintail-1].v) { mintail--; } qmin[mintail++]=node(i,a[i]);//把前k个元素入队 while(maxtail>maxhead&&a[i]>qmax[maxtail-1].v) { maxtail--; } qmax[maxtail++]=node(i,a[i]); } } mini[cnt]=qmin[minhead].v; maxi[cnt++]=qmax[maxhead].v; for(int i=k+1;i<=n;i++) { while(mintail>minhead&&a[i]<qmin[mintail-1].v)//删除比a[i]小的尾元素 { mintail--; } qmin[mintail++]=node(i,a[i]); while(mintail>minhead&&i-k>=qmin[minhead].id)//删除不再范围内的首元素 { minhead++; } while(maxtail>maxhead&&a[i]>qmax[maxtail-1].v) { maxtail--; } qmax[maxtail++]=node(i,a[i]); while(maxtail>maxhead&&i-k>=qmax[maxhead].id) { maxhead++; } mini[cnt]=qmin[minhead].v; maxi[cnt++]=qmax[maxhead].v; } printf("%d",mini[0]); for(int i=1;i<cnt;i++) printf(" %d",mini[i]); printf("\n%d",maxi[0]); for(int i=1;i<cnt;i++) printf(" %d",maxi[i]); printf("\n"); } return 0; }