头像

欢迎来到我的博客

分享题解与总结

P6510 奶牛排队

单调栈

当前序列[a1,a2,a3,...,am,...,an]

后缀最小值:ai成为后缀最小值,当仅ai后面的元素都比它大 \(\forall{j>i},ai<aj\)

后缀最大值:ai成为后缀最小值,当仅ai后面的元素都比它小 \(\forall{j>i},ai>aj\)

P6510 奶牛排队

P6510 奶牛排队 - 洛谷

注:代码中,dec是非严格递减栈,inc是严格递增栈

int n,h[N],p,l,ans;

int main()
{
	ios::sync_with_stdio(0),cin.tie(0);
	cin>>n;
	vector<int> dec,inc;
	//dec:当前红线 找到h[i]左边第一个>=h[i]的数 p
	//inc:历史候选人 以i为右端点,可以作为左端点的候选点 
	//在历史候选人中找到第一个越过红线的人 
	for(int i=1;i<=n;++i){
		cin>>h[i];
	}
	for(int i=1;i<=n;++i){
		while(dec.size()&&h[dec.back()]<h[i]){
			dec.pop_back();
		}
		if(dec.size()) p=dec.back();
		else p=0; 
		//令p=dec.back(),[p+1,i]满足h[i]是最大值 
		//p及其左侧是禁忌,绝对不可能成为(r=i)的合法左端点 
		//但是h[p+1]未必是h[p+1~i]中的最小值 
		//但是此时(r=i)合法的左边界一定在p+1~r之间 
		
		//inc中的任何一个x,均满足h[x]可以作为h[x,i]的后缀最小值
		//h[x]<h[x+1~i] 
		while(inc.size()&&h[inc.back()]>=h[i]){
			inc.pop_back();
		}
		
		//r=i
		//合法的l,需要同时满足[l,r]中h[r]是最大值
		//l:p+1~r之间 
		//且h[l]是[l,r]的最小值
		//l在inc中 
		
		//在inc中找到第一个位置>p的元素	
		if(inc.size()){
			auto it=upper_bound(inc.begin(),inc.end(),p);
			if(it!=inc.end()){
				l=*it;
				ans=max(ans,i-l+1);
			}
		}
	
		dec.push_back(i);
		inc.push_back(i);
	}
	cout<<ans;
	return 0;
}

posted @ 2026-07-17 18:12  king_steph1209  阅读(3)  评论(0)    收藏  举报