m<=s<=k,求满足条件的最长子区间
分析:用两个队列来分别维护最大值和最小值,作为判断条件,如果差值大于k了,就去掉较前面的那个队列元素,并把区间头更新为它的标号+1,
这里注意差值小于m并不需要去掉元素,还有更新答案时要先判断是否满足条件才能更新。
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define nn 100005
using namespace std;
int a[nn],qmax[nn],qmin[nn];
int main()
{
int n,m,k;
while(scanf("%d%d%d",&n,&m,&k)!=EOF)
{
int i,l=0,ans=0,ls=0,lm=0,rs=0,rm=0;
for(i=1;i<=n;i++)
{
scanf("%d",&a[i]);
while(ls<rs&&a[qmin[rs-1]]>a[i]) rs--;
while(lm<rm&&a[qmax[rm-1]]<a[i]) rm--;
qmin[rs++]=i;
qmax[rm++]=i;
if(a[qmax[lm]]-a[qmin[ls]]>k) //如果不满足小于K条件,更新,使i值小的,也就是在前面的被删除
{ //不用考虑<m的情况,因为在前面都满足Max-Min>=m的情况下,加入的点
if(qmin[ls]>qmax[lm]) //要更新Max,只能比Max大,要更新Min,只能比Min小,所以一定成立,不用考虑
{
l=qmax[lm];
lm++;
}
else
{
l=qmin[ls];
ls++;
}
// l=(qmin[ls]<qmax[lm]?qmin[ls++]:qmax[lm++]);
}
if(a[qmax[lm]]-a[qmin[ls]]>=m) //在满足条件的里面选最优,即最长的
{
ans=max(ans,i-l);
}
}
printf("%d\n",ans);
}
return 0;
}