Data Structure - Stack monotone, monotone queue

Reference from: https: //endlesslethe.com/monotone-queue-and-stack-tutorial.html#i-2

Monotonous stack

Examples of a monotonically increasing stack:
push elements are 3,4,2,6,4,5,2,3

Step i operating result
1 3 push 3
2 3 stack into the stack 4 4
3 2 push 4 2
4 2,4 pop, push 6 6
5 4 push 6 4
6 Stack 4, 5 into the stack 6 5
7 2 push 6 5 2
8 2 stack into the stack 3 6 5 3

For an element i:

  • The first section left a large (smaller) than its elements;
  • Determine whether this element is the most value range
  • The right section is greater than its first value
  • The first section to the right a distance greater than its value
  • This element is to determine the most worthy of the longest interval

Code

//在“尾部”添加元素
while (r != 0 || ms[r] <= x) r--;
ms[++r] = x;

//查询栈顶元素
if (r != 0) printf("%d\n", ms[r]);
else printf("-1");

Where x can be replaced by an element onto the stack subscript x to give

Monotonous queue

Monotonically incrementing a queue Examples
queue size can not exceed 3, the elements were 3,2,8,4,5,7,6,4 enqueue

Step i operating result
1 3 into the team 3
2 3 dequeue from the tail, the 2 teams 2
3 8 into the team 2 8
4 8 from the tail dequeued 4 enqueue 2 4
5 5 into the team 2 4 5
6 2 dequeue from the queue head, into the team 7 4 5 7
7 7 from the tail team, the team 6 4 5 6
8 6,5,4 team from the tail, the 4 teams 4
  • The most value can query section (not maintain large range of k)
  • DP optimization

Code

//在“尾部”添加元素x
while (l != r && mq[r] <= x) r--;
mq[++r] = x;

//查询队首元素
if (l != r) printf("%d\n", mq[l+1]);
else printf("-1\n");

//弹出队首元素
if (l != r) l++;

See directly below exercises (continuous collection)

1. POJ 2823 Sliding Window

Link: POJ 2823
** that Italy: ** n and k is to give you, represents the number of elements, and the interval length, the required output starting from 1 to nk each subscripted k is the length of the minimum value output section , and the maximum output.
** Solution: ** Here write monotone queue is the index of the record, and determine what the most current index value can not within the current range, specifically looking at the code.
Code:

//#include <bits/stdc++.h>
#include <cstdio>
#include <iostream>

using namespace std;

const int maxn = 1e6+50;
int n, len, l, r;
int a[maxn];
int mq[maxn];

int main()
{
    scanf("%d %d",&n, &len);
    for(int i = 1; i <= n; i++){
        scanf("%d", &a[i]);
    }
    ///1 3 -1 -3 5 3 6 7
    ///3 2 8 4 5 7 6 4
    l = 0, r = 0;
    for(int i = 1; i <= n; i++){
        while(l != r && a[mq[r-1]] >= a[i]){
            r--;
        }
        mq[r++] = i;
        while(mq[l] <= i - len) l++;
        //for(int j = l; j < r; j++)
        //    cout << a[mq[j]] << " ";
        //cout << endl;
        if(i >= len) cout << a[mq[l]] << " ";
    }
    cout << endl;
    l = 0, r = 0;
    for(int i = 1; i <= n; i++){
        while(l != r && a[mq[r-1]] <= a[i]) r--;
        mq[r++] = i;
        while(mq[l] <= i - len) l++;
        if(i >= len) cout << a[mq[l]] << " ";
    }
    cout << endl;
    return 0;
}

2.POJ 3250 Bad Hair Day

Links: POJ 3250
** meaning of the questions: ** n to the height of your cows, from left to right in order of priority, are looking to the right, now you ask to see the total number of cows per dairy cow can be seen to the right.
** Solution: Monotone queue simple question **
Code:

#include <iostream>
#include <cstdio>

using namespace std;

const int maxn = 1e6+60;
long long n, a[maxn];
long long h[maxn], w[maxn], cur = 0;
long long ans = 0;
const int INF = 0x3f3f3f3f;

void solve()
{
    h[0] = INF+1;
    for(int i = 1; i <= n+1; i++)
    {
        if(a[i] < h[cur])
        {
            h[++cur] = a[i];
            w[cur] = cur-1;
        }
        else
        {
            while(a[i] >= h[cur])
            {
                ans += w[cur];
                h[cur--] = 0;
                if(cur == 0)
                    break;
                //cur--;
            }
            h[++cur] = a[i];
            w[cur] = cur-1;
        }
        if(cur == 0)
            return;
    }
}

int main()
{
    scanf("%lld", &n);
    for(int i = 1; i <= n; i++)
        scanf("%lld", &a[i]);
    a[n+1] = INF;
    solve();
    cout << ans << endl;
    return 0;
}

Published 23 original articles · won praise 6 · views 802

Guess you like

Origin blog.csdn.net/wxy2635618879/article/details/104338284