題目鏈接: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;
}