洛谷P1823 音乐会的等待 (单调栈)

题意分析

对于给出的序列,要处理的是其左边、右边能够看到的人数是多少。
如果我们两边同时计算的话,计算起来就会十分的混乱,最好的办法就是只计算一边的。我这里选择计算左边。

首先理清思路,我们要统计对于序列中的某个元素list[i],在其左边能看到的他的人数个数。 在他左边能看到他的人,身高一定 >= list[i], 最朴素的做法就是从他的位置向左扫描,统计人数。复杂度

### 单调栈算法在洛谷平台上的题目及其解题思路 单调栈是一种高效的线性数据结构,常用于处理涉及区间最值的问题。以下是关于单调栈的相关题目以及其解题思路: #### 1. **最大矩形面积** 此问题的目标是从直方图中找到最大的矩形面积[^2]。 - 使用单调递增栈来维护柱状的高度顺序。 - 对于每个高度 `height[i]`,寻找左侧第一个小于该高度的位置 `left[i]` 和右侧第一个小于该高度的位置 `right[i]`。 - 计算以当前高度为高的矩形宽度 `(right[i] - left[i] - 1)` 并乘以其高得到面积。 ```python def largestRectangleArea(heights): stack = [] heights.append(0) result = 0 for i, h in enumerate(heights): while stack and heights[stack[-1]] >= h: height = heights[stack.pop()] width = i if not stack else i - stack[-1] - 1 result = max(result, height * width) stack.append(i) return result ``` --- #### 2. **接雨水** 目标是计算给定地形能够捕获多少单位的雨水[^5]。 - 构建两个辅助数组 `maxLeft[]` 和 `maxRight[]` 来记录每根柱子左边和右边的最大高度。 - 或者通过两次遍历来实现相同效果:一次从左至右更新 `maxLeft[]`,另一次从右至左更新 `maxRight[]`。 - 结果等于每一位置处可积水的数量之和,即 `min(maxLeft[i], maxRight[i]) - height[i]`。 ```python def trap(height): n = len(height) max_left, max_right = [0]*n, [0]*n water = 0 max_left[0] = height[0] for i in range(1, n): max_left[i] = max(max_left[i-1], height[i]) max_right[n-1] = height[n-1] for i in range(n-2, -1, -1): max_right[i] = max(max_right[i+1], height[i]) for i in range(n): water += min(max_left[i], max_right[i]) - height[i] return water ``` --- #### 3. **离散化与矩形覆盖** 此类问题是将多个大矩形分解成若干个小矩形并统计符合条件的小矩形数量[^4]。 - 利用单调栈确定水平方向上连续未被遮挡的部分作为候选区域。 - 借助前缀和快速查询某一段范围内是否存在特定属性(如属于某个原始矩形)。 ```cpp struct Rect { int lx, ly, rx, ry; }; bool check(Rect r) { /* ... */ } int main() { vector<int> X, Y; // 存储所有边界坐标 sort(X.begin(), X.end()); sort(Y.begin(), Y.end()); long long res = 0; for(int i=0;i<X.size()-1;i++) { for(int j=0;j<Y.size()-1;j++) { double area = (double)(X[i+1]-X[i])*(Y[j+1]-Y[j]); if(check({X[i], Y[j], X[i+1], Y[j+1]})) res += area; } } } ``` --- ### 总结 上述三种类型的题目均体现了单调栈的强大功能,在不同场景下灵活运用可以显著降低时间复杂度。无论是求解最大矩形还是模拟降雨过程中的蓄水情况,核心思想始终围绕着利用栈保存潜在有用的信息以便后续高效检索。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值