【题解】P6510 奶牛排队

题面

题目传送门

前言

呜呜呜,云落好菜

正文

圆规正传

我们枚举 \(B\)

那么 \(A\) 一定是 \(1-B\) 的后缀最小值的位置

并且由于 \(B\) 要是区间最大值,也就是说,第二个后缀最大值的位置一定在 \(A\) 左面

那么我们就通过 第二个后缀最大值的位置,二分出最靠右的 \(A\) 的位置

上面的后缀最大值和后缀最小值就用单调栈求

代码

#include<iostream>
#include<stack>
using namespace std;
const int maxn=1e5+10;
int n,a[maxn];
int stk1[maxn],tp1,stk2[maxn],tp2;
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin>>n;
	int ans=0;
	for(int i=1;i<=n;i++){
		cin>>a[i];
		while(tp1&&a[stk1[tp1]]<a[i]){
			tp1--;
		}
		while(tp2&&a[stk2[tp2]]>a[i]){
			tp2--;
		}
		int l=1,r=tp2,pos=0;
		while(l<=r){
			int mid=l+r>>1;
			if(stk2[mid]>stk1[tp1]){
				r=mid-1;
			}else{
				l=mid+1;
			}
		}
		pos=l;
		if(pos!=tp2+1){
			ans=max(ans,i-stk2[pos]+1);
		}
		stk1[++tp1]=i;
		stk2[++tp2]=i;
	}
	cout<<ans<<endl;
	return 0;
}

后记

日常二分写炸虚空调试

完结撒花!

posted @ 2025-01-21 07:56  sunxuhetai  阅读(56)  评论(0)    收藏  举报