题解 | #愤怒的小鸟#

愤怒的小鸟

https://www.nowcoder.com/practice/597c32f0b3cf43beb1d01e7ddd87cc32

  • 方法:单调栈
  • 思路:
  • 首先找到每个点前面不能到达该点的节点数量:从前向后遍历,记录一个num表示前面所有节点中不能到达当前节点的数目,并维护一个单调递减的栈S。对于第i个节点,如果栈不为空且栈顶元素小于h[i],则一直弹出栈顶元素,并每次把num++,因为这些元素都不能到达当前节点。然后加入当前节点到栈顶,并更新当前节点的ans:ans[i]+=num。
  • 其次找到每个点后面不能到达该点的节点数量:从后往前遍历,其余同上。
  • 注意:单调栈的思想,大多是不单调的节点对后面的节点「没有影响」/「等于对当前节点的影响」。比如这道题中,如果前面某些点不能到达当前节点,那么他们就一定不能达到该节点后面的点,故这些点对后面的节点「等于对当前节点的影响」
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 1e6+10;
int n;
int h[MAXN];
int ans[MAXN];
stack<int>s;
int main() {
    scanf("%d",&n);
    for(int i=1;i<=n;++i)
        scanf("%d",&h[i]);
    int num = 0;
    for(int i=1;i<=n;++i){  //正向,找到每个节点前面不能到达当前节点数目
        while(!s.empty() && s.top()<h[i]){
            s.pop();
            num++;
        }
        s.push(h[i]);
        ans[i]+=num;
    }
    
    num = 0;
    while(!s.empty())s.pop();
    for(int i=n;i>=1;--i){  //逆向,找到每个节点后面不能到达当前节点数目
        while(!s.empty() && s.top()<h[i]){
            s.pop();
            num++;
        }
        s.push(h[i]);
        ans[i]+=num;
    }
    for(int i=1;i<=n;++i){
        printf("%d",ans[i]);
        i==n?printf("\n"):printf(" ");
    }
    
}
// 64 位输出请用 printf("%lld")

全部评论

相关推荐

09-05 21:54
已编辑
湖南工程学院 Java
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务