P6510 奶牛排队
单调栈
当前序列[a1,a2,a3,...,am,...,an]
后缀最小值:ai成为后缀最小值,当仅ai后面的元素都比它大 \(\forall{j>i},ai<aj\)
后缀最大值:ai成为后缀最小值,当仅ai后面的元素都比它小 \(\forall{j>i},ai>aj\)
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;
}

浙公网安备 33010602011771号