题目链接 :
https://www.luogu.com.cn/problem/P2422
题目大意 :
每一天都有一个感受值,定义在一段区间 [ i , j ] 内的舒适程度为 [ i , j ] 区间内最小的感受值 * 区间内感受值的总和,求出最大的舒适程度。
思路 :
区间内感受值的总和可以通过 前缀和 求出。
区间内最小的感受值的求解可以转化,不去确定某个区间内的最小值,而是 确定最小值之后去找区间, 最小值已知,那区间的内所有值都会 大于 它,构造一个 递增的单调队列 ,找到左右第一个比假设最小值小的,两个值之间的区间最小值即是假设的值。
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int MAXN = 100005;
LL ans, a[MAXN], l[MAXN], q[MAXN] = {0}, sum[MAXN], e = 0;
int n;
int main(){
cin >> n;
for (int i = 1; i <= n; i++) scanf("%lld", &a[i]);
a[++n] = 0;
for (int i = 1; i <= n; i++){
sum[i] = sum[i - 1] + a[i];
while (a[i] < a[q[e]]){
l[q[e]] += (sum[i - 1] - sum[q[e]]); //加上右侧的区间和,得到区间内感受值总和
e--;
}
l[i] = sum[i] - sum[q[e]]; //左侧的区间和
q[++e] = i;
}
for (int i = 1; i <= n; i++) ans = max(ans, l[i] * a[i]);
cout << ans << "\n";
return 0;
}