2823: Sliding Window: sliding window problem: Monotone queue principle + + Use template ~

topic

Topic Link
sliding window array of solving the minimum and maximum values
Here Insert Picture Description

Ideas analysis

RMQ segment tree and apparently can be done, but the tree line fight too much trouble, easy to learn method is always good.

Monotone queue is a queue (nonsense)

Wherein the elements of the queue are guaranteed to be monotonically increasing or decreasing monotone

Then the head of the queue element is not the minimum (or maximum) do?

Obviously, when we calculate the interval [ i k + 1 , i ] [i-k+1,i] a maximum value, is not

It is the interval [ i k + 1 , i 1 ] [i-k+1,i-1] We have calculated that before? So we are not trying to save the last result of it (mainly maximum)?

At this time, monotonous queue debut -

There are two operations monotone queue: the head and the tail-deleted

1. Delete the head

If the element head of the queue to leave the range of our current operation , then this element would be no use, we want to delete it, that the head is deleted in order to remove stale data.

2. to tail

The assumption is about to enter the queue elements X X , tail pointer of the queue t a i l tail

Then we have to compare the size of both

  • X q [ t a i l ] X\leq q[tail] : At this time still ensuring the regressive q, it is inserted directly into the queue tail X
  • X > = q [ t a i l ] X>=q[tail] : In this case, decreasing of the queue is broken, at this time we do some operation:
    ① eject the tail elements: since the current q [ t a i l ] q[tail] is not only not the maximum value, the case for the future can not be more than X X better. So this is like the current element to the pop end of the queue is a lack of capacity veterans and new recruits to join the younger, more fight, of course, do veterans
    ② Repeat ①, until meeting X < q [ t a i l ] X<q[tail] or until the queue is empty
    ③ the enqueue XX

For the sample in terms of:

[1 3 -1] -3 5 3 6 7 
q={1},{3},{3,-1} output:3//分别为每次操作的结果
1 [3 -1 -3] 5 3 6 7 
q={3,-1,-3} output:3
1 3 [-1 -3 5] 3 6 7
q={-1,-3},{-1,5},{5} output:5
1 3 -1 [-3 5 3] 6 7
q={5,3} output:5
1 3 -1 -3 [5 3 6] 7 
q={5,6},{6} output:6
1 3 -1 -3 5 [3 6 7]
q={7} output:7

Since each element into the first team at most, once a team (Why?), So the time complexity is THE ( n ) O (n) Of course, this problem can also be done with ST segment tree and table, but are not monotonic convenient queue

Implementation:
Due to perform maintenance on the head of the queue and the tail, so we need to use

Deque

Can use the STL dequemay be handwritten

2 d.front():返回的一个元素的引用。
3 d.back():返回最后一个元素的引用。
4 d.pop_back():删除尾部的元素。不返回值。
5 d.pop_front():删除头部元素。不返回值。
6 d.push_back(e):在队尾添加一个元素e。
7 d.push_front(e):在对头添加一个元素e。

Convenience, we maintain the array index monotonic queue, eliminating the use of paircumbersome or structure:

#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<deque>
#include<vector>
#include<algorithm>
using namespace std;
int n,m;
int a[1000001];
int b[1000001];
int c[1000001];
deque<int> qx,qn;
int cnt;
int main()
{
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        while(!qx.empty()) qx.pop_front();
        while(!qn.empty()) qn.pop_front();
        for(int i=0;i<n;i++)
        scanf("%d",&a[i]);
        for(int i=0;i<n;i++)
        {
            while(!qx.empty()&&a[i]>=a[qx.back()])//判断是否新加得数比前面得大,大的话我们就要把最大值放最前,
                 qx.pop_back();
            qx.push_back(i);
            while(!qn.empty()&&a[i]<=a[qn.back()])
                 qn.pop_back();
            qn.push_back(i);
            if(i>=m-1)
            {
                while(!qx.empty()&&qx.front()<=i-m) qx.pop_front();//我们把出了区间的数踢出队列
                b[cnt]=a[qx.front()];
                while(!qn.empty()&&qn.front()<=i-m) qn.pop_front();
                c[cnt++]=a[qn.front()];
            }
        }
        for(int i=0;i<cnt;i++)
        {
            if(i==0)
            printf("%d",c[i]);
            else printf(" %d",c[i]);
        }
        printf("\n");
        for(int i=0;i<cnt;i++)
        {
            if(i==0)
            printf("%d",b[i]);
            else printf(" %d",b[i]);
        }
        printf("\n");
    }


}
Published 186 original articles · won praise 13 · views 9291

Guess you like

Origin blog.csdn.net/csyifanZhang/article/details/105257494