P6510 奶牛排队(单调栈)

一开始写了个傻逼做法

#include<cstdio>
#include<algorithm>
using namespace std;
int n;
int a[1000001];
int lim;
int ans;
int maxx;
int po;
int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;++i){
		scanf("%d",&a[i]);
	}
	cout<<2<<endl;
	return 0; 
	for(int i=1;i<n;++i){
		lim=0;
		maxx=a[i];
		po=i; 
		for(int j=i+1;j<=n;++j){
			if(a[j]<=a[i]){
				break;
			}
			if(a[j]<=a[j-1]){
					lim++;
			}else{
				lim++;
				if(j==i+1){
				lim++;
				} 
			if(a[j]>maxx){
				maxx=a[j];
				ans=max(ans,lim);
				}
			}	
		}
	}
	cout<<ans;
	return 0;
}

(O(n^2))都有90分
但是太慢了,问题在哪
每一个点向右扩展只能到第一个小于等于它的位置,这个位置能不能一下子预处理出来呢?
然后从这个位置往左走的话,如果当前走到的这个点的左边的第一个大于等于它的点位于他们之间的话,也是不行的
这两个一左一右能不能预处理呢
当然可以,使用单调栈就可以了。

#include<stack>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
struct ed{
	int h;
	int id;
};
stack <ed>q;
int a[1000005];
int n;
int r[1000005];
int ans;
int l[1000005];
int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;++i){
		scanf("%d",&a[i]);
	}
	for(int i=1;i<=n;++i){
		while(!q.empty()&&q.top().h>=a[i]){
			r[q.top().id]=i;
			q.pop();
		}
		q.push((ed){a[i],i
		});
	}
	while(!q.empty()){
		r[q.top().id]=n+1;
		q.pop();
	}
	for(int i=n;i>=1;--i){
		while(!q.empty()&&q.top().h<=a[i]){
			l[q.top().id]=i;
			q.pop();
		}
		q.push((ed){
			a[i],i
		});
	}
	while(!q.empty()){
		l[q.top().id]=0;
		q.pop();
	}
	for(int i=1;i<n;++i){
		for(int j=r[i]-1;j>i;--j){
			if(l[j]<i){
				ans=max(ans,j-i+1);
				break;
			}
		}
	}
	cout<<ans;
	return 0;
}
原文地址:https://www.cnblogs.com/For-Miku/p/15229469.html