2019牛客假日团队赛5_A_Bad Hair Day(单调栈)

26 篇文章 0 订阅
20 篇文章 0 订阅

首先来叙述下我的弱小,把这道题看完之后,第一个反应是——水题。。。然后蒟蒻脑子就是一片空白。。。。。
MD,连水题都不会做,我太菜了,那么先上题https://ac.nowcoder.com/acm/contest/984/A
题目大意:给你一排数列,求从每一位开始一直到比大于等于它的那一位数结束,其中有a[i]位,求所有a[i]之和。
例如:给你一个数列 10 3 7 4 12 2
从10开始一直到12,中间有3个数,即a[1]=3
从3开始一直到7,中间有0个数,即a[2]=0
从7开始一直到12,中间有1个数,即a[3]=1
从4开始一直到12,中间有0个数,即a[4]=0
从12开始一直到末尾,中间有1个数,即a[5]=1
从2开始一直到末尾,中间有0个数,即a[6]=0
那么加起来的总和即为3+1+1=5

当我看到这道题的时候,心里就想,不就是个数列嘛,有什么难的,结果一开始想的思路就不对,卡了1个多小时,多亏了左学长的指点,我才写完(我不会告诉你我在后面的二分上又卡了一个多小时的)

思路:用单调栈,每一次判断是否比栈顶上的元素大,如果大的话,需要将其压入到比需要压入的数大的栈内元素上去
以上面这个数列为例:
第一次,栈内无元素,将10压入;
第二次,栈顶元素为10,3比10小,3压入到10的上面,此时3的贡献值为1
第三次,栈顶元素为3,7比3大,但是7比10小,故将3以上的元素弹出,将7压入到10上面,此时7的贡献值为1
第四次,栈顶元素为7,4比7小,4压入到7上面,此时4的贡献值为2
第五次,栈顶元素为4,12比4大,同时比10大,所以将10以上的元素弹出,将12压入,此时12的贡献值为0
第六次,栈顶元素为12,2比12小,将2压入,此时2的贡献值为1;
求出所有贡献值之和5,即为答案

在每一次压入操作中,我们需要用二分查找来找到每一个数需要压入的位置,然后进行操作,由于本人太菜,在写二分的时候经常搞不懂边界,导致经常出错。。然后这题又卡了一个小时,无颜以对。。。。(为了避免找不到边界的问题,可以试着用用STL— lower_bound()这类函数)

嘛不说了上代码:

#include <bits/stdc++.h>
const int maxn=8e4+7;
using namespace std;
int hi[maxn],n;
int tack[maxn],op=0;
void sech(int x){   
	 if(op==0){      
   			 op++;   
   	 }    
   	 else{        
   	 	int r=op,l=1,mid;        
   	 	while(r-l){     
   			 mid=(l+r)>>1;          
   			  if(tack[mid]>hi[x])                
   			  	l=mid+1;
   			 else               
   			  r=mid;       
   		 }//二分需要处理好边界问题        
   		 op=l;          
   		 if(tack[l]>hi[x])
   		 	op++;    
         //因为每一次比较可能原来栈的大小不会改变,而又需要加入一个新元素鼓此处op++            
   	 }
}
int main(){      
    scanf("%d",&n);        
    for(int i=1;i<=n;i++){              
    scanf("%d",&hi[i]);        
    }        
    long long ans=0;    
    for(int i=1;i<=n;i++){        
        sech(i);        
        ans+=(op-1);          
    	tack[op]=hi[i];    
    }    
    printf("%lld",ans);    
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值