区间最值(单调)
题目:有一列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;
}