HDU 3530 Subsequence(單調隊列)

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


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章