题目链接:
https://nanti.jisuanke.com/t/38228
题意:
给你一个 n n n个整数的序列,定义一个区间 [ l , r ] [l,r] [l,r]的值为 m i n [ l , r ] ∗ ∑ i = l r a [ i ] min_{[l,r]}\ast\sum_{i=l}^ra[i] min[l,r]∗∑i=lra[i],让你求最大的这个值;
分析:
枚举序列中的每个数 a [ i ] a[i] a[i],求以 a [ i ] a[i] a[i]为最小值的最大区间范围;这里用单调栈求区间范围,单调栈可以求出一个序列中左边比它小的第一个数的位置 l [ i ] l[i] l[i],那么 l + 1 l+1 l+1应该是以 a [ i ] a[i] a[i]为最小值的区间最左端点,右边同理 r [ i ] r[i] r[i];如果 a [ i ] > 0 a[i]>0 a[i]>0,那么就是 a [ i ] ∗ ( s u m [ r [ i ] ] − s u m [ l [ i ] ] ) a[i]*(sum[r[i]]-sum[l[i]]) a[i]∗(sum[r[i]]−sum[l[i]])(因为a[i]为正且是该区间最小值),若为负,则查找 [ l [ i ] − 1 , i − 1 ] [l[i]-1,i-1] [l[i]−1,i−1]最大值,及 [ i , r [ i ] ] [i,r[i]] [i,r[i]]中的最大值,可以用线段树解决,然而这里暴力也过了;
代码:
#include <algorithm>
#include <iostream>
#include <cstring>
#include <string>
#include <cstdio>
#include <vector>
#include <queue>
#include <stack>
#include <cmath>
#include <set>
#include <map>
using namespace std;
#define inf 0x7f7f7f7f
#define maxn 500050
#define N 100100
#define P 2
typedef long long ll;
typedef struct {
int u, v, next, w;
} Edge;
Edge e[2];
int cnt, head[1];
inline void add(int u, int v, int w) {
e[cnt].u = u;
e[cnt].v = v;
e[cnt].w = w;
// e[cnt].f=f;
e[cnt].next = head[u];
head[u] = cnt++;
e[cnt].u = v;
e[cnt].v = u;
e[cnt].w = w;
// e[cnt].f=-f;
e[cnt].next = head[v];
head[v] = cnt++;
}
inline void write(int x) {
if (x < 0)
putchar('-'), x = -x;
if (x > 9)
write(x / 10);
putchar(x % 10 + '0');
}
inline int read() {
int x = 0, f = 1;
char c = getchar();
while (c < '0' || c > '9') {
if (c == '-')
f = -1;
c = getchar();
}
while (c >= '0' && c <= '9') {
x = x * 10 + c - '0';
c = getchar();
}
return x * f;
}
int n,a[maxn],l[maxn],r[maxn];
ll sum[maxn];
int main() {
cin>>n;
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
sum[i]=sum[i-1]+a[i];
}
stack<int>s;
while(!s.empty())s.pop();
for(int i=1;i<=n;i++){
while(!s.empty()&&a[s.top()]>=a[i])s.pop();
if(s.empty())l[i]=1;
else l[i]=s.top()+1;
s.push(i);
}
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;
s.push(i);
}
// for(int i=1;i<=n;i++)
// cout<<l[i]<<" "<<r[i]<<endl;
ll res=a[1]*a[1];
for(int i=1;i<=n;i++){
if(a[i]>=0)
res=max((sum[r[i]]-sum[l[i]-1])*a[i],res);
else{
ll maxl=-inf,maxr=inf;
for(int j=l[i]-1;j<=i;j++)
maxl=max(maxl,sum[j]);
for(int j=r[i];j>=i;j--)
maxr=min(maxr,sum[j]);
res=max((maxr-maxl)*a[i],res);
}
}
cout<<res<<endl;
return 0;
}
我们坚持一件事情,并不是因为这样做了会有效果,而是坚信,这样做是对的。
——哈维尔