这题是poj2796的变形,用线段树来维护每个负数的对应的最小区间和
#include<iostream>
#include<stack>
#include<stdio.h>
using namespace std;
#define ls rt<<1
#define rs rt<<1|1
#define ll long long
const int maxn=5e5+100;
struct node
{
int l,r;
ll sum,minn,maxx;
node(int l=0,int r=0,ll sum=0,ll minn=0,ll maxx=0)
{
this->l=l;
this->r=r;
this->sum=sum;
this->minn=minn;
this->maxx=maxx;
}
}tree[maxn<<2];
int L[maxn],R[maxn],a[maxn],n;
ll pre[maxn],ans=-(5e10+10);
stack<int>sta;
void pushup(int rt)
{
tree[rt].sum=tree[ls].sum+tree[rs].sum;
tree[rt].minn=min(tree[ls].minn,tree[rs].minn);
tree[rt].maxx=max(tree[ls].maxx,tree[rs].maxx);
}
void build(int rt,int l,int r)
{
tree[rt].l=l,tree[rt].r=r;
if(l==r)
{
tree[rt].sum=tree[rt].minn=tree[rt].maxx=pre[l];
return ;
}
int mid=(l+r)>>1;
build(ls,l,mid);
build(rs,mid+1,r);
pushup(rt);
}
ll queryminn(int rt,int l,int r)
{
if(tree[rt].l>=l&&tree[rt].r<=r)
return tree[rt].minn;
int mid=(tree[rt].l+tree[rt].r)>>1;
if(r<=mid)
return queryminn(ls,l,r);
else
if(l>mid)
return queryminn(rs,l,r);
else
return min(queryminn(ls,l,mid),queryminn(rs,mid+1,r));
}
ll querymaxx(int rt,int l,int r)
{
if(tree[rt].l>=l&&tree[rt].r<=r)
return tree[rt].maxx;
int mid=(tree[rt].l+tree[rt].r)>>1;
if(r<=mid)
return querymaxx(ls,l,r);
else
if(l>mid)
return querymaxx(rs,l,r);
else
return max(querymaxx(ls,l,mid),querymaxx(rs,mid+1,r));
}
int main()
{
scanf("%d",&n);
a[0]=-1e5-10;;
a[n+1]=-1e5-10;
for(int i=1;i<=n;i++) scanf("%d",&a[i]),pre[i]=pre[i-1]+a[i];
build(1,1,n);
for(int i=1;i<=n+1;i++)
{
if(sta.empty()||a[i]>=a[sta.top()])
sta.push(i);
else
{
while(!sta.empty()&&a[i]<a[sta.top()])
{
R[sta.top()]=i-1;
sta.pop();
}
sta.push(i);
}
}
sta.pop();
for(int i=n;i>=0;i--)
{
if(sta.empty()||a[i]>=a[sta.top()])
sta.push(i);
else
{
while(!sta.empty()&&a[i]<a[sta.top()])
{
L[sta.top()]=i+1;
sta.pop();
}
sta.push(i);
}
}
for(int i=1;i<=n;i++)
{
if(a[i]>=0)
ans=max(ans,(pre[R[i]]-pre[L[i]-1])*a[i]);
else
ans=max(ans,(queryminn(1,i,R[i])-((L[i]==i)?pre[i-1]:querymaxx(1,L[i],i-1)))*a[i]);
}
printf("%lld
",ans);
return 0;
}