先前接触了单调队列的题,确实是很重要的知识点,单调队列不难,就是用栈或队列来通过对队头的判断来实现队列保持单调。
题意:
给出一个大小为n的数组a[n];
求其中最大值减最小值在【m,k】中的字串最长长度。
思路:
用两个单调队列分别维护a【i】前元素中的最大值与最小值的下标,top为最值。
然后当最值之差过大时,a【i】的满足题意的最长字串为最最后操作last与【i】的距离 其中last取离i最远的一个
这样就出来了,单调队列主要是在于数组操作上,要将数组各种变量与题意紧紧联系起来。。。
代码:
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
inline int max(int a ,int b){return a>b?a:b;}
const int N = 100010;
int s1[N],s2[N];
int a[N];
int main()
{
int n,m,k,top1,top2,last1,last2,tail1,tail2,ans;
while(scanf("%d%d%d",&n,&m,&k)!=EOF)
{
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
}
memset(s1,0,sizeof(s1));
memset(s2,0,sizeof(s2));
top1=0;top2=0;tail1=0;tail2=0;ans=0;last1=0;last2=0;
for(int i=1;i<=n;i++)
{
//max
while(top1<tail1&&a[s1[tail1-1]]<=a[i])tail1--; //top1最大元素
s1[tail1++]=i;
//min
while(top2<tail2&&a[s2[tail2-1]]>=a[i])tail2--; //top2最小元素
s2[tail2++]=i;
while(a[s1[top1]]-a[s2[top2]]>k)
{
if(s1[top1]<s2[top2])
last1=s1[top1++];
else last2=s2[top2++];
}
if(a[s1[top1]]-a[s2[top2]]>=m)
{
ans=max(ans,i-max(last1,last2));
}
}
cout<<ans<<endl;
}
return 0;
}