单调栈与单调队列

单调栈
单调栈就是栈内元素保持单调性的栈
遍历整个序列,每一次从栈顶弹出会破坏单调性的元素,最后将当前元素加入栈顶
由于每个元素最多入栈一次,出栈一次,所以可以在(O(n))的时间复杂度内处理数据
相关题目:hdu1506 Largest Rectangle in a Histogram

#include<iostream>
#include<cstdio>
#include<vector>
#include<stack>
#include<queue>
#include<set>
#include<map>
#include<cstring>
#include<string>
#include<sstream>
#include<cmath>
#include<ctime>
#include<algorithm>
#define LL long long
#define PII pair<int,int>
#define PLL pair<LL,LL>
#define pi acos(-1.0)
#define eps 1e-6
#define lowbit(x) x&(-x)
using namespace std;

const int maxn=100010;
int n,h[maxn],L[maxn],R[maxn],stk[maxn];

void solve(){
    int t=0;
    for(int i=0;i<n;i++){
        while(t>0 && h[stk[t-1]]>=h[i]) t--;
        L[i]=(t==0?0:(stk[t-1]+1));
        stk[t++]=i;
    }
    t=0;
    for(int i=n-1;i>=0;i--){
        while(t>0 && h[stk[t-1]]>=h[i]) t--;
        R[i]=(t==0?n:stk[t-1]);
        stk[t++]=i;
    } 
    LL ans=0;
    for(int i=0;i<n;i++){
        ans=max(ans,(LL)(R[i]-L[i])*h[i]);
    }
    printf("%lld
",ans);
}

int main(void){
    while(scanf("%d",&n)!=EOF && n){
        for(int i=0;i<n;i++) scanf("%d",&h[i]);
        solve();
    }
    return 0;
}

单调队列
单调队列就是队内元素保持单调性的队列
单调队列可以维护固定长度的区间的最值
遍历整个序列,每一次从队尾删除会破坏单调性的元素,从队头删除“过期”的元素,最后将当前元素加入队尾
由于每个元素最多入队一次,出队一次,所以可以在(O(n))的时间复杂度内完成数据处理
相关题目:hdu3415 Max Sum of Max-K-sub-sequence

#include<iostream>
#include<cstdio>
#include<vector>
#include<stack>
#include<queue>
#include<set>
#include<map>
#include<cstring>
#include<string>
#include<sstream>
#include<cmath>
#include<ctime>
#include<algorithm>
#define LL long long
#define PII pair<int,int>
#define PLL pair<LL,LL>
#define pi acos(-1.0)
#define eps 1e-6
#define lowbit(x) x&(-x)
using namespace std;

int T,n,k,a[100010],sum[200010],deq[200010];

int main(void){
    scanf("%d",&T);
    while(T--){
        scanf("%d %d",&n,&k);
        a[0]=sum[0]=0;
        for(int i=1;i<=n;i++){
            scanf("%d",&a[i]);
            sum[i]=sum[i-1]+a[i];
        }
        for(int i=n+1;i<n+k;i++){
            sum[i]=sum[i-1]+a[i-n];
        }
        deq[0]=0;
        int ans=INT_MIN,st,ed,s=0,t=1,len;
        for(int i=1;i<n+k;i++){
            if(deq[s]<i-k){
                s++;
            }
            if(ans<sum[i]-sum[deq[s]] || ans==sum[i]-sum[deq[s]] && len>i-deq[s]){
                ans=sum[i]-sum[deq[s]];
                len=i-deq[s];
                st=deq[s]+1;
                ed=i;
            }
            while(s<t && sum[deq[t-1]]>sum[i]){
                t--;
            }
            deq[t++]=i;
        }
        if(st>n) st-=n;
        if(ed>n) ed-=n;
        printf("%d %d %d
",ans,st,ed);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/fxq1304/p/13427172.html