题意:
给n个数,每段区间的和等于的区间内最小值乘以区间内每个数的和的最大值,求最大的区间值
思路:
难点在于有负数,如果只有正数,单调栈板子就可以处理,(太菜了,比赛的时候不会处理负数,虽然听说别人用单调栈或线段树或单调栈加线段树过了这个题,但是自己毫无思路)
然后下来以后看了别人的代码,只学会了暴力的方法;
计算每个数i以i为最小值的区间的最左值和最右值,注意如果i是负数,就计算以i为最小值的区间和最小的最左值和最右值,然后暴力跑一边就好了
暴力代码:
#include<bits/stdc++.h>
#define fastio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
using namespace std;
typedef long long ll;
#define fi first
#define se second
const int maxn=5e5+10;
ll l[maxn],r[maxn],a[maxn],sum[maxn];
int main()
{
fastio
ll n;
cin>>n;
sum[0]=0;
a[0]=a[n+1]=-1e18;//记得处理边界,
for(ll i=1;i<=n;i++){
cin>>a[i];
sum[i]=sum[i-1]+a[i];
l[i]=r[i]=i;
}
for(ll i=1;i<=n;i++){//求区间最左值
if(a[i]>0){
while(a[i]<=a[l[i]-1]) l[i]=l[l[i]-1];
}
else if(a[i]<0){//负数要特殊处理
ll x=a[i],y=l[i];
while(a[i]<=a[l[i]-1]){
l[i]=l[l[i]-1];
if(sum[i]-sum[l[i]-1]<x){
x=sum[i]-sum[l[i]-1];
y=l[i];
}
}
l[i]=y;
}
}
for(ll i=n;i>=1;i--){//求区间最右值
if(a[i]>0){
while(a[i]<=a[r[i]+1]) r[i]=r[r[i]+1];
}
else if(a[i]<0){//负数要特殊处理
ll x=a[i],y=r[i];
while(a[i]<=a[r[i]+1]){
r[i]=r[r[i]+1];
if(sum[r[i]]-sum[i-1]<x){
x=sum[r[i]]-sum[i-1];
y=r[i];
}
}
r[i]=y;
}
}
ll ans=0;
for(ll i=1;i<=n;i++) ans=max(ans,a[i]*(sum[r[i]]-sum[l[i]-1]));//暴力跑一边求最大值
cout<<ans<<endl;
return 0;
}