还是一个单调队列题目
题干如下
给定一段序列,求出最长的一段子序列使得该子序列中最大最小只差x满足m<=x<=k。
那么建立两个单调队列,一个维护递增,一个维护递减,这样我们能够快速求出极值差,而当差值一旦大于 k 记录一下两个队列距离队尾最近的左端点,然后当符合条件时,不断更新最长长度。。。
以下是AC代码
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 1e5+5;
int qmx[maxn],qmi[maxn];//递增,递减
int num[maxn],n,m,k;
int main()
{
while(~scanf("%d%d%d",&n,&m,&k))
{
for(int i=1;i<=n;i++)
scanf("%d",&num[i]);
int head_min=0,head_max=0;
int tail_min=0,tail_max=0;
int left1=0,left2=0;
int maxx=0;
for(int i=1;i<=n;i++)
{
while(head_min<tail_min&&num[qmi[tail_min-1]]<=num[i])
tail_min--;
while(head_max<tail_max&&num[qmx[tail_max-1]]>=num[i])
tail_max--;
qmx[tail_max++]=qmi[tail_min++]=i;
while(num[qmi[head_min]]-num[qmx[head_max]]>k)
{
if(qmi[head_min]<qmx[head_max])
left1=qmi[head_min++];
else
left2=qmx[head_max++];
}
if(num[qmi[head_min]]-num[qmx[head_max]]>=m)
maxx=max(maxx,i-max(left1,left2));
}
printf("%d\n",maxx);
}
return 0;
}