题目链接: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; }