题目链接:https://nanti.jisuanke.com/t/38228
题意:求区间和*区间最小值 的最大值
题解:先单调栈求一下以每个位置为最小值的左右到哪,线段树维护下前缀的最大最小值,然后当前值为正值时,就让可选区间范围内区间的值最大,右边取个最大,左边取个最小,当前值为负数时,让可选区间的值最小,左边取个最小,右边取个最大
#include<bits/stdc++.h>
using namespace std;
const int N=5e5+10;
typedef long long ll;
struct node
{
int l,r;
ll maxx,minn;
}tree[N<<2];
ll sum[N],a[N];
int n;
int l[N],r[N];
void pushup(int cur)
{
tree[cur].maxx=max(tree[cur<<1].maxx,tree[cur<<1|1].maxx);
tree[cur].minn=min(tree[cur<<1].minn,tree[cur<<1|1].minn);
}
void build(int l,int r,int cur)
{
tree[cur].l=l;
tree[cur].r=r;
if(l==r)
{
tree[cur].maxx=tree[cur].minn=sum[l];
return;
}
int mid=(r+l)>>1;
build(l,mid,cur<<1);
build(mid+1,r,cur<<1|1);
pushup(cur);
// cout<<l<<" "<<r<<" "<<tree[cur].l<<" "<<tree[cur].maxx<<" "<<tree[cur].minn<<endl;
}
ll querymax(int pl,int pr,int cur)
{
if(pl<=tree[cur].l&&tree[cur].r<=pr)
{
return tree[cur].maxx;
}
ll res=-1e18;
if(pl<=tree[cur<<1].r) res=max(res,querymax(pl,pr,cur<<1));
if(pr>=tree[cur<<1|1].l) res=max(res,querymax(pl,pr,cur<<1|1));
return res;
}
ll querymin(int pl,int pr,int cur)
{
if(pl<=tree[cur].l&&tree[cur].r<=pr)
{
return tree[cur].minn;
}
ll res=1e18;
if(pl<=tree[cur<<1].r) res=min(res,querymin(pl,pr,cur<<1));
if(pr>=tree[cur<<1|1].l) res=min(res,querymin(pl,pr,cur<<1|1));
return res;
}
int main()
{
while(~scanf("%d",&n))
{
for(int i=1;i<=n;i++)
{
scanf("%lld",&a[i]);
sum[i]=sum[i-1]+a[i];
}
stack<int> s;
for(int i=1;i<=n;i++)
{
while(!s.empty() && a[s.top()] >= a[i]) s.pop();
if(s.empty()) l[i]=0;
else
{
l[i]=s.top();
// cout<<s.top()<<" "<<a[s.top()]<<" " <<a[i]<<" "<<(!s.empty() && a[s.top()] >= a[i])<<endl;
}
s.push(i);
// cout<<l[i]<<endl;
}
while(!s.empty()) s.pop();
for(int i=n;i>=1;i--)
{
while(!s.empty() && a[s.top()] >= a[i]) s.pop();
if(s.empty()) r[i]=n;
else r[i]=s.top()-1;
// cout<<r[i]<<endl;
s.push(i);
}
build(0,n,1);
ll ans=-1e18,cnt;
for(int i=1;i<=n;i++)
{
cnt=a[i];
// cout<<l[i]<<" "<<i-1<<" "<<i<<" "<<r[i]<<endl;
if(cnt>0) cnt=cnt*(querymax(i,r[i],1)-querymin(l[i],i-1,1));
else cnt=cnt*(querymin(i,r[i],1)-querymax(l[i],i-1,1));
// cout<<cnt<<endl;
ans=max(ans,cnt);
}
printf("%lld\n",ans);
}
return 0;
}
/*
4
-3 -6 -9 1
4
2 -5 6 -9
*/