--这个系列题解以后完善,持续更新,目前主要用于保存代码QWQ
这次好多都是原题升级版,然鹅眼熟又有什么用呢.jpg
这题是POJ2796升级版,我个人认为是一道很不错的题目。
单调栈+ST表,单调栈就不提,ST表可得当前点i的合法区间的rmq,对于负数点i,i点右边的min减去i点左边的max可得包含i点在内的最小子区间。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int topp,b[500005],c[500005],a[500005];
ll summ[500005],ffmax[500005][20],ffmin[500005][20];
struct node
{
int num;
int val;
}s[500005];
ll querymax(int l,int r)
{
int k=log2(r-l+1);
return max(ffmax[l][k],ffmax[r-(1<<k)+1][k]);
}
ll querymin(int l,int r)
{
int k=log2(r-l+1);
return min(ffmin[l][k],ffmin[r-(1<<k)+1][k]);
}
int main()
{
int n,m,i,j,k,num,sum;
ll ans;
// while(~scanf("%d",&n))
// {
scanf("%d",&n);
for(i=1;i<=n;i++)
scanf("%lld",&a[i]);
for(i=1;i<=n;i++)
summ[i]=summ[i-1]+a[i];
for(i=0;i<=n;i++)
ffmin[i][0]=ffmax[i][0]=summ[i];
for(i=1;(1<<i)<=n+1;i++)
for(j=0;j+(1<<i)<=n+1;j++)
{
ffmax[j][i]=max(ffmax[j][i-1],ffmax[j+(1<<(i-1))][i-1]);
ffmin[j][i]=min(ffmin[j][i-1],ffmin[j+(1<<(i-1))][i-1]);
}
for(i=1;i<=n;i++)
{
while(topp>=1&&s[topp].val>=a[i]) topp--;
if(topp==0) b[i]=0;
else b[i]=s[topp].num;
s[++topp].num=i,s[topp].val=a[i];
}
topp=0;
for(i=n;i>=1;i--)
{
while(topp>=1&&s[topp].val>=a[i]) topp--;
if(topp==0) c[i]=n+1;
else c[i]=s[topp].num;
s[++topp].num=i,s[topp].val=a[i];
}
ans=-1e18;
for(i=1;i<=n;i++)
{
if(a[i]>=0)
ans=max(ans,a[i]*(summ[c[i]-1]-summ[b[i]]));
else
{
ans=max(ans,(querymin(i,c[i]-1)-querymax(b[i],i-1))*(ll)a[i]);
}
}
printf("%lld\n",ans);
// }
return 0;
}