题目链接:Click here~~
题意:
给一个长度为 n 的序列,找出最长的子序列满足 子序列中的最大值和最小值 的差在区间 [m,k] 范围内。
解题思路:
维护两个单调队列,分别存最小值和最大值。
利用 two pointer 的思想,用 j 指向正在考虑中的区间左端点位置,出队时不断右移左指针 j,对于每个 i 不断更新 ans。
Ps.也可以根据贪心的思想,出队时每次删除较小的位置,但需要不断维护两个队列中的最小位置,写法没 two pointer 优美。
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
const int N = 1e5 + 5;
int a[N],qmin[N],qmax[N];
int main()
{
int n,m,k;
while(~scanf("%d%d%d",&n,&m,&k))
{
for(int i=0;i<n;i++)
scanf("%d",&a[i]);
int head1 = 0 , rear1 = -1;
int head2 = 0 , rear2 = -1;
int ans = 0;
for(int i=0,j=0;i<n;i++)
{
while(head1 <= rear1 && a[ qmin[rear1] ] >= a[i])
rear1--;
qmin[++rear1] = i;
while(head2 <= rear2 && a[ qmax[rear2] ] <= a[i])
rear2--;
qmax[++rear2] = i;
while(a[ qmax[head2] ] - a[ qmin[head1] ] > k)
{
if(j == qmin[head1])
++head1;
if(j == qmax[head2])
++head2;
j++;
}
if(j <= i && a[ qmax[head2] ] - a[ qmin[head1] ] >= m)
ans = max(ans,i-j+1);
}
printf("%d\n",ans);
}
return 0;
}