区间最值(单调)

区间最值(单调)

题目:有一列n个数字a[1]…a[n],对所有1<=L<=R<=n求max(a[L],a[L+1],…,a[R])
并求和, n<=1e6
这是一道单调栈的应用题,如果用暴力枚举区间然后枚举一个数,那么将会是n3的复杂度,太慢了吧…
所有,我们需要反过来,枚举每一个数在哪些区间里是最大的,不用盲目的去枚举这么多区间,我们枚举这个数在哪一个区间最大就好了,所以我们需要卡一个端点,这个端点a是比我们枚举的点b大,那么以这两个点为区间的b是最大值
所以这个样子就能确定两个点
思路就是这样,接下来是代码实现

#include<cstdio>
#include<algorithm>
#include<string>
#include<cstring>
#include<iostream> 
using namespace std;
const int SIZE=1e6+5;
int n,a[SIZE];
int ans;
int last,f[SIZE];//f[i]表示i~n区间的最大和的值
int main()
{
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		cin>>a[i];
	}
	last=f[n]=a[n];
	for(int i=n-1;i>0;i--)
	{
		int temp=lower_bound(a+i+1,a+n+1,a[i])-a;//单调查找第一个大于a[i]的数 如题所述
		 
		f[i]+=(temp-i)*a[i];//求i在区间的最值 
		f[i]+=f[temp];//求temp在区间的最值 
	}
	for(int i=1;i<=n;i++)
	{
		ans+=f[i];
	}
	cout<<ans<<"\n";//求答案 
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值