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;
}
有问题请评论或私信我,谢谢!