HDU3530(单调队列)

题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=3530

题意

  给出一个数列 ai ,及一个范围 [m,k] ,求这个数列中所有连续的区间的最大值与最小值之差在[m,k]中,的区间长度最大是多少。

思路(单调队列+尺取法)

  满足某一要求,求最大或最小区间长度很容易想到尺取法,而怎么快速求某一区间的最大最小值,很容易想到RMQ之类的算法,比如线段树、ST表、树状数组等,但是尺取法本身就是区间滑动的过程,所以也可以通过单调队列顺便求出区间的最大值和最小值,总体思路没什么问题,需要注意一个问题:左右端点如何滑动。
  设左右端点为L,R,如果当前区间满足条件,那么应该尽可能的扩大区间,直到不能扩大为止,这个之后缩小左端点,L++直到满足条件,对每一次满足条件后的区间长度求一次max。最大值和最小值分别用两个单调队列记录。

#include
using namespace std;
#define maxn 1000009
#define ll long long
#define inf 1000000009000000000
#define IOS ios::sync_with_stdio(false)

int ff[maxn];
pair dq1[maxn],dq2[maxn];

int main()
{
    IOS;
    int n,m,k;
    while(cin>>n>>m>>k)
    {
        for(int i=1; i<=n; i++)
            cin>>ff[i];

        int L=1,ans=0;
        int le1=1,ri1=1;
        int le2=1,ri2=1;
        for(int i=1; i<=n; i++)
        {
            if(le1==ri1)
                dq1[ri1++]=make_pair(i,ff[i]);
            else
            {
                while(le1!=ri1&&dq1[ri1-1].second>ff[i])
                    ri1--;
                dq1[ri1++]=make_pair(i,ff[i]);
            }

            if(le2==ri2)
                dq2[ri2++]=make_pair(i,ff[i]);
            else
            {
                while(le2!=ri2&&dq2[ri2-1].secondk)
            {
                L++;
                if(le1!=ri1&&dq1[le1].first=m)
            {
                ans=max(ans,i-L+1);
                //cout<<"asn="<

你可能感兴趣的:(单调队列,尺取法,单调队列,尺取法)