专栏文章
题解:P12241 [蓝桥杯 2023 国 C] 最大区间
P12241题解参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @mipjnk8k
- 此快照首次捕获于
- 2025/12/03 13:05 3 个月前
- 此快照最后确认于
- 2025/12/03 13:05 3 个月前
题意简述
给定一个长度为 的序列,求最大的 的值,就是区间长度乘以区间最小值的最大值。
算法思路
通过正向逆向两次单调栈扫描预处理,找出每个点作为区间最小点能获得的最大区间,很明显,区间越长越好。有一道极其相似的题:洛谷 P2422 良好的感觉。
-
确定左右边界:
- 先初始化,初始化左端点为 ,右端点为 。
- 正向逆向跑一遍单调栈,求出每个点左边和右边第一个比 小的点的位置。
- 此时 作为最小值的最大区间为 ,实际正确的区间长度为 ,因为是以 为最小点的区间。
-
计算时注意: 区间不包含左右端点。
复杂度分析
- 时间复杂度: 正向逆向各一次扫描。
代码实现
CPP#include<cstdio>
#include<stack>
#include<climits>
#include<algorithm>
using namespace std;
typedef long long ll;
const ll maxn = 3e5 + 5;
ll n, num[maxn];
void Input() {
scanf("%lld", &n);
for (ll i = 1; i <= n; ++i) {
scanf("%lld", &num[i]);
}
}
ll l[maxn], r[maxn];
void Init() {
for (ll i = 1; i <= n; ++i) {
l[i] = 0;
r[i] = n + 1;
}
}
stack<ll> s;
ll ans = INT_MIN;
void Sol() {
for (ll i = 1; i <= n; ++i) {
while (!s.empty() && num[s.top()] > num[i]) {
r[s.top()] = i;
s.pop();
}
s.push(i);
}
while (!s.empty()) {
s.pop();
}
for (ll i = n; i >= 1; --i) {
while (!s.empty() && num[s.top()] > num[i]) {
l[s.top()] = i;
s.pop();
}
s.push(i);
}
for (ll i = 1; i <= n; ++i) {
ans = max(ans, ((r[i] - 1) - (l[i] + 1) + 1) * num[i]);
}
}
int main() {
Input();
Init();
Sol();
printf("%lld", ans);
return 0;
}
注意:初始化时左右边界分别为 和 。
相关推荐
评论
共 0 条评论,欢迎与作者交流。
正在加载评论...