当青训营遇上码上掘金 攒青豆

67 阅读1分钟

当青训营遇上码上掘金

题目描述

现有 n 个宽度为 1 的柱子,给出 n 个非负整数依次表示柱子的高度,排列后如下图所示,此时均匀从上空向下撒青豆,计算按此排列的柱子能接住多少青豆。(不考虑边角堆积)

725ef710a59944d49d0315bece7a1ac1_tplv-k3u1fbpfcp-zoom-in-crop-mark_4536_0_0_0.webp

以下为上图例子的解析:

输入:height = [5,0,2,1,4,0,1,0,3]  
输出:17  
解析:上面是由数组 [5,0,2,1,4,0,1,0,3] 表示的柱子高度,在这种情况下,可以接 17 个单位的青豆。

思路解析

我们可以发现从一侧去考虑,我们只会计算“凹地”中的豆子数,然后累计到我们的答案中,并且我们会发现其高度的变化是具有单调性的,所以我们可以使用类似单调栈的方式来解决本问题,可以在线性的时间复杂度内完成对本体的求解。

  • 维护一个单调减小的栈,若当前柱子高于栈顶的柱子,退栈直到符合单调性;否则加入栈顶。
  • 每次退栈时,累加豆子的体积(每次算一层)。
  • 最后栈是一个单调栈,结束程序即可。

以下使用c++c++实现示例代码。

#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;
}