单调队列有部分堆的功能,但其只能维护给定区间中比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\n",ans); } return 0; }
原文地址:https://www.cnblogs.com/zsben991126/p/10140237.html
时间: 2024-10-11 03:53:15