P2866 [USACO06NOV] Bad Hair Day S(单调栈)

Bad Hair Day S

传送门:

P2866 [USACO06NOV] Bad Hair Day S - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

思路

构建思路的初步少不了暴力

	rep(i,1,n){
		rep(j,i+1,n){
			if(a[i]>a[j]) sum++;
			else break;
		}
	}

AC9个点,TLE一个点

题目的本意是在位置i往前看可以看到几个比他大的,但是如果有两个比它大的,靠后的那个遮住了靠前的那个就会看不见前面那个(这里以从左到右为向前的方向),如图
图形化

如a,能看到e,只要f小于等于e,a都看不见,因为e遮住了f

但是如果我们以这样的方式做,向前找永远都要和前面那个我们要看牛的这个牛的高度作比较,如果是这样的话,时间复杂度很难优化一般都要在n2,可能大佬们可以优化一下,但是我这种大佬蒟蒻是优化不来的 。
所以我们要把思路转换,转换成每一个前面的牛牛可以看到几个后面的。那前面看后面是看小的,后面看前面就是看大的,如果靠前的大的遮住了靠后的小的就是遮住了看不到了,实际上思路是一样的,但是这样我们每次只要往前考虑,遮住了就丢掉,就不用管从后往前遮住了的情况

	stack<int>s;
	rep(i,1,n){
		while(!s.empty()&&s.top()<=a[i]){
			s.pop();
			/*
			如果遇到前面的比后面的大的就直接pop,
			用自然语言表述就是后面的被前面的遮住了
			那再靠前的就看不见这些被遮住的了
			*/
		}
		sum+=s.size();//这边sum要定义成long long因为sum最大值可能在n^2
		s.push(a[i]);//把当前牛牛放进去
	}

这边要感谢 陈炫8 提出关于/**/注释更方便童鞋们学习的建议

有共同学习需求的可以加入洛谷团队:https://www.luogu.com.cn/team/66731

AC code

// Problem: 
//     P2866 [USACO06NOV] Bad Hair Day S
//   
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P2866
// Memory Limit: 125 MB
// Time Limit: 1000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include<iostream>
#include<algorithm>
//#include<cstdio>
#include<stack>
#define ll long long 
#define endl '\n'
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define per(i,a,b) for(int i=(a);i>=(b);i--)
#define N 80010 //1e6+100 
 
using namespace std;
int n,a[N];
stack<int>s;
ll sum;
int main(){
	//ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
	cin>>n;
	rep(i,1,n) cin>>a[i];
	rep(i,1,n){
		while(!s.empty()&&s.top()<=a[i]){
			s.pop();
		}
		sum+=s.size();
		s.push(a[i]);
	}
	cout<<sum;
	return 0; 
} 





有问题请评论或私信我,谢谢!

  • 7
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值