#单调栈#洛谷 6510 奶牛排队 题目 分析 代码

问长度超过1的最长的区间([i,j])满足区间最小值为(a_i)
区间最大值为(a_j),且其余数在区间((a_i,a_j))范围内,没有输出0


分析

枚举右端点,考虑维护一个单调递增和一个单调不递增的的单调栈,
那么单调不递增的栈顶一定不小于右端点的值,
那么在单调递增的点中选择栈顶位置的后继即为左端点,
这样保证了左端点尽量小,并且左端点与右端点之间
不存在任意数超过右端点的值或小于左端点的值


代码

#include <cstdio>
#include <cctype>
#include <algorithm>
#define rr register
using namespace std;
const int N=100011;
int n,a[N],stmn[N],stmx[N],ans,topmx,topmn;
inline signed iut(){
	rr int ans=0; rr char c=getchar();
	while (!isdigit(c)) c=getchar();
	while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
	return ans;
}
inline void print(int ans){
	if (ans>9) print(ans/10);
	putchar(ans%10+48);
}
signed main(){
	n=iut();
	for (rr int i=1;i<=n;++i) a[i]=iut();
	for (rr int i=1;i<=n;++i){
		while (topmn&&a[stmn[topmn]]>=a[i]) --topmn;
		while (topmx&&a[stmx[topmx]]<a[i]) --topmx;
		rr int pos=upper_bound(stmn+1,stmn+1+topmn,stmx[topmx])-stmn;
		if (pos<=topmn) ans=max(ans,i-stmn[pos]+1);
		stmn[++topmn]=stmx[++topmx]=i;
	}
	return !printf("%d",ans);
}