【数据结构】骚操作--单调栈

以cf622(Div.2)的C2题为例讲解一下吧:
**题意:**就是找单峰值。建设大楼,要求每栋楼有限高,而且不允许存在一栋楼两边都有比他更高的楼,要求建成的楼总高度最大。

这里我们引入一个单调栈的东西:花了2小时才算勉强搞明白了(感谢wucstdio大佬)
在这里插入图片描述
这里运用单调栈来做的话,时间复杂度只有O(n),难点在于这个单调栈该如何去写。下面上ac的代码,里面单调栈的部分运用了2次,分别是求上升的单调栈和下降的单调栈。在这里我对上升的单调栈进行了注释,下降的单调栈其本质类似,所以不加赘述。

#include<bits/stdc++.h>
#define ll long long
using namespace std;
int n,a[500005];
int st[500005],num[500005],top;
ll s[500005],pre[500005],suf[500005];
ll ans,pos;
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++)scanf("%d",&a[i]);
	for(int i=1;i<=n;i++)
	{
		ll now=1;
		while(top&&a[i]<=st[top])  //如果top存在并且当前访问值a[i]小于等于前一个top值 
		{
			now+=num[top];		   //需要更改的长度值+=top所占据的长度	
			top--;				   //把top的位置向前移动 
		}
		st[++top]=a[i];            //更改top的值为当前的a[i] 
		num[top]=now;			   //更改当前top所占据的长度 
		s[top]=s[top-1]+now*a[i];  //当前top的前缀和=前一个top的前缀和+当前的top(a[i])*其所霸占的长度	
		pre[i]=s[top];
	}
	top=0;
	for(int i=n;i>=1;i--)
	{
		ll now=1;
		while(top&&a[i]<=st[top])
		{
			now+=num[top];
			top--;
		}
		st[++top]=a[i];
		num[top]=now;
		s[top]=s[top-1]+now*a[i];
		suf[i]=s[top];
	}
	for(int i=1;i<=n;i++)
	{
		if(ans<pre[i]+suf[i]-a[i])
		{
			ans=pre[i]+suf[i]-a[i];
			pos=i;
		}
	}
	for(int i=pos-1;i>=1;i--)a[i]=min(a[i],a[i+1]);
	for(int i=pos+1;i<=n;i++)a[i]=min(a[i],a[i-1]);
	for(int i=1;i<=n;i++)printf("%d ",a[i]);
	printf("\n");
	return 0;
}
发布了90 篇原创文章 · 获赞 6 · 访问量 5010

猜你喜欢

转载自blog.csdn.net/Rainfoo/article/details/104476841