当青训营遇上码上掘金
题目描述
现有 n 个宽度为 1 的柱子,给出 n 个非负整数依次表示柱子的高度,排列后如下图所示,此时均匀从上空向下撒青豆,计算按此排列的柱子能接住多少青豆。(不考虑边角堆积)
以下为上图例子的解析:
输入:height = [5,0,2,1,4,0,1,0,3]
输出:17
解析:上面是由数组 [5,0,2,1,4,0,1,0,3] 表示的柱子高度,在这种情况下,可以接 17 个单位的青豆。
思路解析
我们可以发现从一侧去考虑,我们只会计算“凹地”中的豆子数,然后累计到我们的答案中,并且我们会发现其高度的变化是具有单调性的,所以我们可以使用类似单调栈的方式来解决本问题,可以在线性的时间复杂度内完成对本体的求解。
- 维护一个单调减小的栈,若当前柱子高于栈顶的柱子,退栈直到符合单调性;否则加入栈顶。
- 每次退栈时,累加豆子的体积(每次算一层)。
- 最后栈是一个单调栈,结束程序即可。
以下使用实现示例代码。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e5+5;
int a[maxn];
int main(){
int n,res=0;
cin>>n;
for(int i=0;i<n;i++)cin>>a[i];
stack<int>st;
for (int i=0;i<n;i++){
while(!st.empty()&&a[st.top()]<a[i]){
int t=st.top();
st.pop();
if (!st.empty()){
int l=i-st.top()-1;
int h=min(a[i],a[st.top()])-a[t];
res+=l*h;
}
}
st.push(i);
}
cout<<res<<endl;
return 0;
}