hdu3530 双单调队列的维护

单调队列有部分堆的功能,但其只能维护给定区间中比v大的值或者比v小的值,且其一般存储元素的下标。

思路:两个单调队列维护最大值与最小值的下标,如果区间的最大值最小值之差大于给定范围,则选择队首靠左的删去,并记录删去元素的下标,然后维护最大区间长度即可

注意有两个范围,第二个范围不能忽略

/*
单调队列存储区间最大值,最小值
如果Max-Min>k,呢么左端点靠前的删掉队头元素,删掉时记录下标 
*/
#include<iostream>
#include<cstring>
#include<cstdio>
#define maxn 100005

using namespace std;

int n,m,k,a[maxn],q_max[maxn],q_min[maxn];

int main(){
    while(scanf("%d%d%d",&n,&m,&k)==3){
        for(int i=1;i<=n;i++) scanf("%d",&a[i]);
        int l_min=0,r_min=0,l_max=0,r_max=0;
        int last1=0,last2=0,ans=0;
        
        for(int i=1;i<=n;i++){
            //队尾插入元素
            while(l_min<r_min&&a[q_min[r_min-1]]>=a[i]) r_min--;
            while(l_max<r_max&&a[q_max[r_max-1]]<=a[i]) r_max--;
            q_min[r_min++]=q_max[r_max++]=i;
            while(a[q_max[l_max]]-a[q_min[l_min]]>k){
                if(q_max[l_max]<q_min[l_min]) last2=q_max[l_max++];
                else last1=q_min[l_min++];
            } 
            if(a[q_max[l_max]]-a[q_min[l_min]]>=m)//这个条件还是要判的 
            ans=max(ans,i-max(last1,last2));
        }
        printf("%d
",ans);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/zsben991126/p/10140237.html