12.3日总结 单调栈

这篇博客介绍了如何使用单调栈解决一道编程题目——计算奶牛能看到的发型数量。通过建立单调递增栈,找到每个奶牛向右看到的第一个比它高的奶牛,从而计算出每只奶牛能看到的发型总数,并最终求和。代码实现中涉及栈的操作包括入栈、出栈以及判断条件。虽然理解过程有些抽象,但通过坚持不懈的学习,可以掌握这一解题技巧。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

今天就刷了两个题,尝试了一个题,

主要看了单调栈,

单调栈分为两种一中是栈中元素从栈顶到栈顶呈从小到大的排序的栈这样的栈称为单调递增栈

另一种从栈顶到栈底数据从大到小称为单调递减栈

单调栈的应用一般可以用来求这样两类问题

1.视野总和问题

就是下面的这个问题

Farmer John的奶牛在风中凌乱了它们的发型……
每只奶牛都有一个身高hi(1 ≤ hi ≤ 1,000,000,000),现在在这里有一排全部面向右方的奶牛,一共有N只(1 ≤ N ≤ 80,000)。对于奶牛i来说,如果奶牛i+1,i+2,……,N这些奶牛的身高严格小于奶牛i,则奶牛i可以看到它们凌乱的发型。
比如下面这个例子:

* * * * = *
= * * * = *
= * - * = * 奶牛面向这边-->
= * = * = *
= - = = = *
= = = = = =
1 2 3 4 5 6
('*'表示空的,这是译者为了格式特意弄的,原题没有)

令ci表示第i只奶牛能够看到的发型数量,请计算c1 + c2 + c3 + … + cN的值
对于上面这个例子,答案为3 + 0 + 1 + 0 + 1 + 0=5。

输入

第一行:奶牛数量N
第二到N+1行:第i+1行输入奶牛i的身高

输出

第一行:一个整数即c1到cN的和

样例输入

6
10
3
7
4
12
2

样例输出

5

解题思路是

观察题之后,我们发现实际上题目转化为找当前数字向右查找的第一个大于他的数字之间有多少个数字,然后将每个结果累计就是答案,我们使用单调栈来解决这个问题。

1.设置一个单调递增的栈(栈内0~n为单调递减)
2.当遇到大于栈顶的元素,开始更新之前不高于当前人所能看到的值

附上代码

#include<stdio.h>
int main()
{
    int n;
    long long a[80005];//用来接收输入数字的数组,根据题目要求必须是longlong形的
    long long stack[80005];//自定义堆栈
    int i;
    int top=0;//栈内元素.
    long long sum=0;//用来累加结果的
    scanf("%d",&n);
    for(i=1;i<=n;i++)
    {
        scanf("%lld",&a[i]);
    }
      for(int i=1;i<=n;i++)
     {
        if(top==0||a[stack[top]]>a[i])//如果栈为空或者入栈元素大于栈顶元素则入栈
            stack[++top]=i;//用下标来储存数据
        else
            if(a[stack[top]]<=a[i])//如果栈顶元素小于或者等于入栈元素则出栈
            {

                while(a[stack[top]]<=a[i]&&top!=0)
              {
                sum+=i-1-stack[top];
                top--;
              }
                stack[++top]=i;//入栈。
             }
       }
          for(i=1;i<top;i++)//剩下栈内元素可以看到多少人要一起加,
         sum=sum+n-stack[i];
        printf("%lld",sum);
}
明天要团建啊,好烦感觉心思有点动摇了,因为我觉得理解起来好抽象的哦

咬咬牙坚持住吧

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值