20pts
枚举所有可能的左端点、右端点,时间复杂度 O ( n 2 ) O(n^2) O(n2)。
对于每个区间进行遍历检测,时间复杂度 O ( n 3 ) O(n^3) O(n3)。
100pts
由于数据范围为 1 0 5 10^5 105,所以肯定只能进行一次枚举。
我们尝试枚举右端点,当一个点作为右端点时,那么,该点可能是最大值,也可能是次大值,较难实现。
尝试枚举每个点作为次大值点,那么,若 a [ x ] a[x] a[x] 作为次大值点,我们需要做的就是,找出左侧的第一个 ≥ a [ x ] \geq a[x] ≥a[x] 的点,假设坐标为 y y y,那么他俩一定可以构成一个区间,区间大小为 x − y + 1 x - y + 1 x−y+1。
同理,可以找出右侧第一个 ≥ a [ x ] \geq a[x] ≥a[x] 的点,假设坐标为 y y y,那么区间大小为 y − x + 1 y - x + 1 y−x+1。
此处,我们可以使用单调栈进行查找左侧第一个大于自己的下标,以及右侧第一个大于自己的下标。
时间复杂度 O ( n ) O(n) O(n)。
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <stack>using namespace std;const int N = 1e5 + 10;int n;
int a[N];
int lef[N], rig[N];int main()
{ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);cin >> n;for (int i = 1; i <= n; ++ i )cin >> a[i];a[0] = a[n + 1] = 2e9;stack<int> stk;stk.push(0);for (int i = 1; i <= n; ++ i ){while (a[stk.top()] < a[i])stk.pop();lef[i] = stk.top();stk.push(i);}while (stk.size())stk.pop();stk.push(n + 1);for (int i = n; i; -- i ){while (a[stk.top()] < a[i])stk.pop();rig[i] = stk.top();stk.push(i);}int res = 0;for (int i = 1; i <= n; ++ i ){if (lef[i] != 0)res = max(res, i - lef[i] + 1);if (rig[i] != n + 1)res = max(res, rig[i] - i + 1);}cout << res << endl;return 0;
}