单调栈问题,小白月赛H,Hdu-1506

单调栈问题:

1、特征:

栈内的所有元素都保持一个单调性,

eg:

递增的单调栈:顶端元素永远大于下面的元素

递减的单调栈:顶端元素永远小于下面的元素;

2、作用:

寻找从左到右,和从右到左第一个大于/小于当前元素的位置。

这篇文章的递木板倒水问题为例

hdu-1506

思路:

记录当前元素递增的可扩展的最长的左边元素L数组,最长的右边元素R数组。

参考文章

#include<iostream>
#include<cstdio>
#include<cstring>
#include<stack>
using namespace std;
const int maxn = 300300;
typedef long long LL;
LL a[maxn],L[maxn],R[maxn];
LL MAX(LL x,LL y){
    return x>y?x:y;
}
int main(void)
{
    stack <LL> st;
    int n,i,j;
    while(~scanf("%d",&n)&&n){
        while(!st.empty()) st.pop();
        st.push(0);
        for(i=1;i<=n+1;i++){
            if(i<=n) scanf("%lld",&a[i]);
            else a[i] = 0;
            L[i] = R[i] = i;
            while(st.size()>1&&a[st.top()]>=a[i]){
                R[st.top()] = i-1;
                st.pop();
            }
            L[i] = st.top();
            st.push(i);
        }
        LL ans = 0;
        for(i=1;i<=n;i++){
            ans = MAX(ans,(R[i]-L[i])*a[i]);
        }
        printf("%lld\n",ans);
    }
    return 0;
} 

H--小A的柱状图

思路:和上一题的基本相同,就是用前缀和处理一下宽度。

#include<iostream>
#include<cstdio>
#include<stack>
#include<cstring>
using namespace std;
typedef long long LL;
const int maxn = 1000300;
LL a[maxn],L[maxn],R[maxn],h[maxn],pre[maxn]={0};
LL MAX(LL x,LL y){
	return x>y?x:y;
}
int main(void)
{
	stack <LL> st;
	st.push(0);
	int n,i,j;
	scanf("%d",&n);
	for(i=1;i<=n;i++){
		scanf("%lld",&a[i]);
		pre[i] = pre[i-1]+a[i];
	}
	for(i=1;i<=n+1;i++){
		if(i<=n) scanf("%lld",&h[i]);
		else h[i] = 0;
		L[i] = R[i] = i;
		while(st.size()>1&&h[st.top()]>=h[i]){
			R[st.top()] = i-1;
			st.pop();
		}
		L[i] = st.top();
		st.push(i);
	}
	LL ans = 0;
	for(i=1;i<=n;i++){
		ans = MAX(ans,(pre[R[i]]-pre[L[i]])*h[i]);
	}
	printf("%lld\n",ans);
} 

猜你喜欢

转载自blog.csdn.net/qq_41829060/article/details/89361780