sliding window queue cogs 495. monotone

495. The sliding window

★★ Input file: window.in   Output file: window.out   a simple comparison of
the time limit: 2 s memory limit: 256 MB

【Problem Description】

 

Give you an array of length N, a length K of the sliding form from the leftmost to the extreme right, you can see the K number of windows, each window moves to the right one, in the following table:

Window position Min value Max value
[1 3 -1] -3 5 3 6 7 -1 3
[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 find a window max value at each position, min value.

 

[Input Format]

 

The first line n, k, the second line array of length n

 

[Output format]

 

The first line for each position of the min value, a second row position of each max value

 

[O] Sample

window.in
8 3
1 3 -1 -3 5 3 6 7

window.out
-1 -3 -3 -3 3 3
3 3 5 5 6 7

【data range】

 

20%:n≤500; 50%:n≤100000;100%:n≤1000000;

 

For many years not knock (heart can not help but wonder I have a total scholarship for a few years!?) Monotonous queue ready to review the matter out of the path of the sliding window is a very classic introductory title Rights (gosh I'm still brush the entry title)

First of all queues in the end what is it monotonous? First to introduce a good thing stl

and < int > N;

what is this?

This is called double-ended queue queue QUEUE we usually are on the right into the right side of

This is about double-ended queue can out of it

(Of course, you can also manually build an array to simulate manual)

 

So we talk a long time or have not talked about what is monotonous queue

Some operation is guaranteed monotonic to queue

What is monotonic?

In fact, it is to keep the queue elements are monotonically increasing or monotonically decreasing

 

Theoretical knowledge finally finished

Now we are speaking about how to use such a monotonically increasing or decreasing the monotony out of both ends can queue to solve this right questions

 

Let's come and collect a minimum interval to this example it is monotonically increasing queue is at the top is minimal

First, we have the first element of the queue into the monotonous 

Next we have to operate with the second element

First, we put a second element which is added to the queue (if it is smaller than the first element)

We start with a visit to enumerate first while loop is smaller than the current second element is clear from the queue

Apparently now only own a second element

If you want to enumerate the minimum interval length is 2 then it is the minimum to the first section we find an array to record the current enumeration zone to end zone for the location of the position

That is the tail that we can not become larger minimum interval of about popback

We also performed an action is to kick out all obsolete elements from the queue

比如枚举到了第4个元素 区间的长度是2   假如2现在还在队列里之前一直没有被踢掉 它就不属于当前枚举的区间了  我们就要把它从队列里踢出去

那么怎样知道应该踢出去谁呢?首先2这个节点肯定是队列中现存的位置中最靠前的 也就是说他是最先放进去的  但是却一直没有被更新掉 仔细地想一想 它肯定是在队列的最前面

我们只需要popfront一下就行了

 

此时我们维护的单调队列是递增的  也就是说最小的排在最前面 我们在取最小值的时候只需要把单调队列中的队首元素取出来就行了

 

 

至于区间最大值 也是基本类似的  只是单调队列变成了递减的  排在队首的是最大的

 

具体看代码 我相信您肯快就会明白 我这么弱的都看懂了

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<string>
#include<cstring>
#include<deque>
using namespace std;
int v[1000005],minn[1000005],maxx[1000005];
int n,k;
void Min()//递增 
{
    deque<int> q;
    int i;
    q.push_back(1);
    minn[1]=v[1];
    for(int i=2;i<=n;i++)
    {
        while(!q.empty()&&v[q.back()]>v[i])
            q.pop_back();//把队尾不合法的都弹出去反正也不会是最小的,因为有比他们更小的 
        q.push_back(i);//放进去 
        while(!q.empty()&&q.front()<i-k+1)
            q.pop_front();//把过时的都弹出去 
        minn[i]=v[q.front()];//剩下的合法的最小的是队头 
    }
    
}
void Max()//递减 
{
    deque<int> q;
    int i;
    q.push_back(1);
    maxx[1]=v[1];
    for(int i=2;i<=n;i++)
    {
        while(!q.empty()&&v[q.back()]<v[i])
            q.pop_back();
        q.push_back(i);
        while(!q.empty()&&q.front()<i-k+1)
            q.pop_front();
        maxx[i]=v[q.front()];
    }
}
int main()
{
    
    scanf("%d%d",&n,&k);
    
    for(int i=1;i<=n;i++)
        scanf("%d",&v[i]);
    Min();
    Max();
    for(int i=k;i<n;i++)
        printf("%d ",minn[i]);
    printf("%d\n",minn[n]);
    for(int i=k;i<n;i++)
        printf("%d ",maxx[i]);
    printf("%d",maxx[n]);
    return 0;
}

 

Guess you like

Origin www.cnblogs.com/Tidoblogs/p/11409813.html