[Data Structure] substantially monotonous application stack

[Data Structure] substantially monotonous application stack

A monotonous stack implementation

1. Definitions

Briefly, the stack is a monotonous ensure that its internal elements monotonically increasing or decreasing monotonically data structure.
That stack maintains monotonically from the bottom to the top element of the stack monotonicity.

2. Implementation

For monotonically decreasing stack:

. A If the current stack is empty, stack unconditionally;

. b If the top of the stack is greater than when the element to be pushed onto the stack, the stack;

. c If the top of the stack is less than equal to the time until the stack of elements, the first element constantly pop the stack until the stack of elements to be greater than the top element, or until the stack is empty, and push the element;

Here are monotonically decreasing the stack core code:

for(int i=1;i<=n;i++){
    scanf("%d",&a);
    while(top&&a>=Stack[top]) top--;
    //求单调上升栈只须将">="改为"<="
    Stack[++top]=i;
}

Second, the basic application stack monotonous

Monotone stack advantage lies in its complexity is O (n), because each element only once into the stack, the stack again.
The following is a monotonous stack of basic applications:

A sequence of determined positions within a [i] to the left or right section first interval is greater than or less than the value a [i] is

Example. 1: P2947 [USACO09MAR] Xiangyoukanqi Look Up

Description Title: Given a sequence of a, find a first section ai right position is greater than ai.
Thinking: if we enumerate the violence of words, complexity is \ (O (the n-^ 2) \) , is bound to overtime. So we use monotonous stack.
From left to right scan the entire sequence and maintains a strict no increase in the stack (because the topics explained only if hi> hj i will look when cows cow j).
Code:

#include<bits/stdc++.h>
#define N 120000
using namespace std;
int h,n,top,ans[N];
struct node{
    int pos,h;
}q[N];
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%d",&h);
        while(top&&h>q[top].h){
            ans[q[top].pos]=i;
            top--; 
        }
        q[++top]=(node){i,h};
    }
    for(int i=1;i<=n;i++) printf("%d\n",ans[i]);
    return 0; 
}

Example 2: P1901 transmitting station

Description Title: Given a sequence of a, ai seeking left and right sections a first section is greater than the weight and position ai.
Ideas: we can either consider a patchwork of ai by which point, you can also consider the composition of ai answer what factors.
For the latter, we can easily think of monotonous stack. Whenever a new element into the shells, if greater than the top element, and then continue to pop the top element to the accumulated weight of the new element. If a new element is less than the top element, the new element to the right of the top element to the accumulated value. Continue to operate like this, you can get a final answer.
Code:

#include<bits/stdc++.h>
#define ll long long
#define N 1000010
using namespace std;
ll Stack[N],n,top,ans[N];
struct node{
    ll h,v;
}p[N];
int main()
{
    scanf("%lld",&n);
    for(int i=1;i<=n;i++){
        scanf("%lld%lld",&p[i].h,&p[i].v);
        while(top&&p[i].h>p[Stack[top]].h){
            ans[i]+=p[Stack[top]].v;
            top--;
        }
        ans[Stack[top]]+=p[i].v;
        Stack[++top]=i;
    }
    ll res=0;
    for(int i=1;i<=n;i++) res=max(res,ans[i]);
    printf("%lld",res);
    return 0;
}

Three cases: P2659 beautiful sequence

Description Title: seeking a sequence (of any section of the interval * min), and.
Ideas: a very good question monotonous stack. Similarly, we can either enumerate all of the interval to calculate the final answer. Obviously, we can not afford such enormous complexity of the time. On the contrary, if we consider a sequence number as min intervals can affect the range, multiply this number will be able to get the answer we want. In this case, the problem will be converted for the sake of right and left ai ai is less than the first position. The rise stack just good at solving such problems. Refer to code specifically explained.
Code (there is provided another way):

#include<bits/stdc++.h>
#define ll long long
#define N 2000010
using namespace std;
int Stack[N],top,n;
ll a[N],l[N],r[N],ans;
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    //分别从左扫描,右扫描,求出ai最大影响区间 
    for(int i=1;i<=n;i++){ 
        while(top&&a[Stack[top]]>=a[i]) l[i]+=l[Stack[top--]];
        //若新元素的值比栈顶要小,此时该元素能延伸到的左区间范围必然会包含栈顶元素延伸的范围
        //而此时栈内元素是单调上升的,故累加的左区间不会重叠而保证正确性 
        l[i]++;
        Stack[++top]=i;
    }
    top=0;
    for(int i=n;i>=1;i--){
        while(top&&a[Stack[top]]>=a[i]) r[i]+=r[Stack[top--]];
        //同上,只是扫描方向相反而已 
        r[i]++;
        Stack[++top]=i;
    }
    for(int i=1;i<=n;i++)//注意影响区间是(li+ri-1) 
        ans=max(ans,(l[i]+r[i]-1)*a[i]);
    printf("%lld\n",ans);
    return 0;
}

Of course, there are also provided on a similar question wording:

for(int i=1;i<=n;i++) l[i]=0,r[i]=n+1;//赋初值
for(int i=1;i<=n;++i){
    while(top&&a[Stack[top]]>=a[i]) r[Stack[top]]=i,top--;//栈顶元素被新元素所影响
    l[i]=Stack[top];//此时新元素不在有能力影响此时栈顶的元素,可以确定li
    Stack[++top]=i;
}

Example. 4: P1823 [COI2007] Patrik wait concert

Subject description:This enhanced version of the transmitting station entitled.For a given sequence a, ai a value greater than the determined first position.
Ideas: In order to avoid repetition count, right to left, we need to find the first position is greater than ai. Since the monotonous stack has a dichotomy, so we just need to find half of this value decreases monotonically in the stack on it. Finally, only a total answer to.
Code:

#include<bits/stdc++.h>
#define N 500010
#define ll long long
using namespace std;
ll ans;
int Stack[N],a[N],n,top;
inline void erfen(int x){
    int l=0,r=top,res=0;
    while(l<=r){
        int mid=(l+r)>>1;
        if(a[Stack[mid]]>x){
            l=mid+1;
            res=mid;
        }
        else r=mid-1;
    }
    if(res>0) ans+=top-res+1;
    else ans+=top; 
}
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    for(int i=1;i<=n;i++){
        erfen(a[i]);
        while(top&&a[i]>a[Stack[top]]) top--;
        Stack[++top]=i;
    }
    printf("%lld",ans);
    return 0;
}

III Summary

1. We maintain monotonically rising stack to find the location of the first ai less than
2. We find maintenance monotonically decreasing first stack to a position greater than ai
3. We can stack get monotone ai is the maximum scope min or max

Guess you like

Origin www.cnblogs.com/cyanigence-oi/p/11706494.html