poj 2823 Sliding Window(单调队列)

来源:互联网 发布:头皮里面长痘痘 知乎 编辑:程序博客网 时间:2024/06/15 18:55

Description

An array of size n ≤ 10^6 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.
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

大致题意:给你一个数组a[],然后让你求这个数组中连续k个元素的最大值和最小值,按顺序分两行输出。

思路:用单调队列来写。
对于单调队列,我们这样子来定义:
1、维护区间最值
2、去除冗杂状态 ,区间中的两个元素a[i],a[j](假设现在再求最小值) 若 j>i且a[j]<=a[i] ,a[j]比a[i]还小而且还在后面(目前a[j]留在队列肯定比a[i]有用,所以你就可以把a[i]出队,即tail–)
3、保持队列单调,最小值是单调递增序列,最小值反之
4、最优选择在队首

大致过程:
1、维护队首(head++)
2、在队尾插入(每插入一个就要从队尾开始往前去除冗杂状态,tail–)

代码如下

#include<iostream>#include<algorithm>#include<string>#include<cstdio>#include<cstring>#include<cstdlib>#include<queue>#include<vector>#include<cstring>#define LL long long int using namespace std;const int N=1e6+5;struct node{    int num;    int cost;    node(int _num=0,int _cost=0):num(_num),cost(_cost){}}q[N];int n,k;int a[N];int Max[N];int Min[N];void getmin(){    int head=1,tail=1;    int i;    for(i=1;i<=k-1;i++)    {        while(head<tail&&a[i]<=q[tail-1].cost) tail--;        q[tail++]=node(i,a[i]);    }    for(;i<=n;i++)    {        while(head<tail&&a[i]<=q[tail-1].cost) tail--;        q[tail++]=node(i,a[i]);        while(q[head].num<i-k+1) head++;        Min[i-k+1]=q[head].cost;    }}void getmax(){    int head=1,tail=1;    int i;    for(i=1;i<=k-1;i++)    {        while(head<tail&&a[i]>=q[tail-1].cost) tail--;        q[tail++]=node(i,a[i]);    }    for(;i<=n;i++)    {        while(head<tail&&a[i]>=q[tail-1].cost) tail--;        q[tail++]=node(i,a[i]);        while(q[head].num<i-k+1) head++;        Max[i-k+1]=q[head].cost;    }}int main(){    scanf("%d%d",&n,&k);    for(int i=1;i<=n;i++)    scanf("%d",&a[i]);     getmin();    getmax();    for(int i=1;i<=n-k+1;i++)    {        if(i==1)        printf("%d",Min[i]);        else         printf(" %d",Min[i]);    }    printf("\n");    for(int i=1;i<=n-k+1;i++)     {        if(i==1)        printf("%d",Max[i]);        else         printf(" %d",Max[i]);    }    printf("\n");    return 0;}

(不过用G++或GCC交会超时。。。需要用C++交,之前用了二分优化进队时的操作也没什么太好的效果,。,。目前就先这样好了,改天再回来优化。。。。)

原创粉丝点击