知识点:单调栈
这个题的难度还是给高了一点,其实就是绿题,一开始,看到这个题我想着用尺取法加单调队列来解决,用单调队列来维护尺取区间的最小值,但是我发现这个题给的条件很少,尺取法需要一定的条件来满足单调性使得遍历区间可以在线性时间内完成,然后我再看看就发现这个不就是单调栈的题目吗,完全和求最大子矩阵面积一模一样,每一个数,都是一个正方形,然后看看这些正方形排一起,最大子矩阵的面积是多少,这个式子就是这个含义,然后用单调栈做就行了,
这个题的坑点还是比较多的,首先是多组数据,其次是这个没有SPJ,面积最大的时候,我们要输出下边个数最少的,如果还一样,那么输入左下标最小的,但是这个我是从左向右遍历的,所以一直满足这个要求,就不用考虑,然后就是我用了前缀和这个题,一开始没有开long long,也是错了好几次,最后一个问题就是这个题的数据会有一个全零的,如果按照我一开始的写法,那么无法找到最短的区间,一个办法就是初始化答案数据为第一个元素的值,区间就是1,1,这样就把那种特殊情况包含进去了
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 5;
long long a[N], b[N];
int main() {
int n;
int T = 0;
while (cin >> n) {
if (T++) cout << endl;
for (int i = 1; i <= n; i++) {
cin >> a[i];
b[i] = b[i - 1] + a[i];
}
int L[N], R[N];
fill(L + 1, L + n + 1, 0);
fill(R + 1, R + n + 1, n + 1);
stack<int> s1;
for (int i = 1; i <= n; i++) {
while (!s1.empty() && a[i] < a[s1.top()]) {
R[s1.top()] = i;
s1.pop();
}
s1.push(i);
}
stack<int> s2;
for (int i = n; i >= 1; i--) {
while (!s2.empty() && a[i] < a[s2.top()]) {
L[s2.top()] = i;
s2.pop();
}
s2.push(i);
}
long long ans = a[1];
int x = 1, y = 1;
for (int i = 1; i <= n; i++) {
long long tmp = a[i] * (b[R[i] - 1] - b[L[i]]);
if (tmp > ans) {
ans = tmp;
x = L[i] + 1;
y = R[i] - 1;
} else if (tmp == ans && R[i] - L[i] - 2 < y - x) {
x = L[i] + 1;
y = R[i] - 1;
}
}
cout << ans << endl << x << " " << y << endl;
}
return 0;
}