Maximum value (monotonic queue)

Time limit: 1 Sec Memory limit: 128 MB
[Submit] [Status] The
title description
gives N integers and a length value of Len. In these N integers, each length is the maximum value of a continuous segment of Len. .

For example: N=8, Len=3, 8 integers are: 2 5 1 1 2 4 7 1. The answer is 5 5 2 4 7 7.
Explanation:
The maximum value of 2 5 1 is 5
5 The maximum value of
1 1 is 5 1 The maximum value of 2 is 2
1 The maximum value of 4 is 4
2 4 The maximum value of 7 is 7
4 7 The maximum value of 1 is 7
Enter
2 positive integers in the first line: N, Len. N range [2...100000], Len range [2...N] The
second line: N positive integers, each number range [1...1000000000].
Output
one line, N-Len+1 integers.
Sample input Copy

4 3
7 2 1 4

Sample output Copy

7 4

The meaning of the question is very simple, which is to find the maximum value of all elements in [i,i+len], where the range of i is [1,n-len].
Violence obviously won't work. I first used priority queue + queue (save each maximum value) to do it, and found that it would disrupt the original sequence of the sequence, and then consider dp, but I still have no idea. Finally, Baidu took a look. You can use deque to do it.
Deque is also a kind of container. It can insert (push_front()) and delete (pop_front()) operations at the head of the queue, or insert (push_back()) and delete (pop_back()) at the end of the queue. You can also access the element at the head of the team (front()). Combining the meaning of the question, we can maintain a decreasing queue, so that the head element of the visited queue is exactly the maximum value in the interval.
The key to this question is how to insert and delete elements.
Insertion : In order to ensure the decrement of the monotonic queue, when we insert element xx (struct x type), we must compare the element at the end of the queue with the a member of xx (representing the data of the element), if the element at the end of the queue is not greater than a, delete the element at the end of the team, and then continue to compare the new element at the end of the team with a, until the element at the end of the team is greater than a, at this time we insert xx to the end of the team.
Delete : Since we only need to save the maximum value of len elements, when the subscript of the element at the head of the team is less than or equal to i-len, it means that the element at the head of the team has no meaning for seeking the maximum value. ( Note that it is not to delete the head element after each cycle, but to determine according to the subscript of the head element, because sometimes the elements in a monotonic queue may not be len ) So when index<=i-len, Delete the head element.
Simulate an example:

8 3
2 5 1 1 2 4 7 1
3个元素:2 5 1
i=12入队
i=22出队,5入队,队中元素为5
i=31入队,队中元素为5 1

i=41入队,队中元素为5 1 1
i=5,队首元素5的下标为2,不在范围内,5出队;2>11出队,1出队,2入队,队中元素为2
i=6,队首元素为22<42出队,4入队,队中元素为4
i=7,队首元素为44<74出队,7入队,队中元素为7
i=8,队首元素为77>11入队,队中元素为71
显然i>=3时每步的队首元素就是所求的最大值(5 5 2 4 7 7)

This problem is similar to the monotonic stack problem I wrote before .

#include<cstdio>
#include<queue>
#include<deque>
using namespace std;
struct x
{
    
    
    int index;
    int a;
};
struct x xx[100005];
queue<int>ans;
deque<struct x>b;
int main()
{
    
    
    int n,len,i;
    scanf("%d %d",&n,&len);
    for(i=1;i<=n;i++)
    {
    
    
        scanf("%d",&xx[i].a);
        xx[i].index=i;
    }
    for(i=1;i<=len;i++)//前len个元素单独处理
    {
    
    
        while(!b.empty()&&b.back().a<=xx[i].a)b.pop_back();
        b.push_back(xx[i]);
    }
    ans.push(b.front().a);//队首元素放入队列,等待最后输出
    for(i=len+1;i<=n;i++)
    {
    
    
        while(!b.empty()&&b.front().index<=i-len)b.pop_front();
        while(!b.empty()&&b.back().a<=xx[i].a)b.pop_back();
        b.push_back(xx[i]);
        ans.push(b.front().a);//队首元素放入队列,等待最后输出
    }
    printf("%d",ans.front());//注意最后一个数字后面没有空格
    ans.pop();
    while(!ans.empty())
    {
    
    
        printf(" %d",ans.front());
        ans.pop();
    }
    return 0;
}
/**************************************************************
    Language: C++
    Result: 正确
    Time:37 ms
    Memory:2860 kb
****************************************************************/

This question can also be done with the ST table.

#include<cstdio>
#include<queue>
#include<algorithm>
using namespace std;
int st_table[100005][20];
int a[100005];
int Log[100005];
queue<int>ans;
int main()
{
    
    
    int n,i,j,len;
    scanf("%d %d",&n,&len);
    for(i=1;i<=n;i++)scanf("%d",&a[i]);
    for(i=1;i<=n;i++)st_table[i][0]=a[i];
    Log[1]=0;
    for(i=2;i<=n;i++)Log[i]=Log[i/2]+1;
    for(j=1;(1<<j)<=n;j++)
    {
    
    
        for(i=1;i+(1<<j)-1<=n;i++)
        {
    
    
            st_table[i][j]=max(st_table[i][j-1],st_table[i+(1<<(j-1))][j-1]);//注意是i+(1<<(j-1)),不是i+(1<<j)
        }
    }
    for(i=1;i<=n-len+1;i++)
    {
    
    
        ans.push(max(st_table[i][Log[len]],st_table[i+len-(1<<Log[len])][Log[len]]));//区间长度别忘了+1
    }
    printf("%d",ans.front());
    ans.pop();
    while(!ans.empty())
    {
    
    
        printf(" %d",ans.front());
        ans.pop();
    }
    return 0;
}
/**************************************************************
    Language: C++
    Result: 正确
    Time:49 ms
    Memory:10664 kb
****************************************************************/

Guess you like

Origin blog.csdn.net/upc122/article/details/105739699