2096:[Poi2010]Pilots单调队列题解

时间:2017-01-11  |  来源:cnphp6

Description

Tz又耍畸形了!!他要当飞行员,他拿到了一个飞行员测试难度序列,他设定了一个难度差的最大值,在序列中他想找到一个最长的子串,任意两个难度差不会超过他设定的最大值。耍畸形一个人是不行的,于是他找到了你。

Input

输入:第一行两个有空格隔开的整数k(0<=k<=2000,000,000),n(1<=n<=3000,000),k代表Tz设定的最大值,n代表难度序列的长度。第二行为n个由空格隔开的整数ai(1<=ai<=2000,000,000),表示难度序列。

Output

输出:最大的字串长度。

Sample Input

3 9
5 1 3 5 8 6 6 9 10

Sample Output

4
(有两个子串的长度为4: 5, 8, 6, 6 和8, 6, 6, 9.最长子串的长度就是4)
题解:这个就是单调队列的裸题啦,不过需要我们同时维护一个最大和一个最小的队列,唔,单调队列我就不细讲了,不过这道题具体实现的时候我出了一点的问题所以具体怎么写还是看注释吧:
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
using namespace std;
long long tot,k,n,f1[3000010],f2[3000010];
long long t1,t2,head1,head2,ans,a[3000010];
int main()
{
    scanf("%d %d",&k,&n);
    for (int i=1;i<=n;i++) scanf("%d",&a[i]);
    t1=t2=0;
    head1=head2=1;
    ans=1;
    for (int i=1;i<=n;i++)
    {
           while ((a[i]>a[f1[t1]])&&(t1>=head1)) t1-=1;//维护最大值
       while ((a[i]<a[f2[t2]])&&(t2>=head2)) t2-=1;//维护最小值
       t1+=1; t2+=1;
       f1[t1]=i;//记录下当前这个值的位置
       f2[t2]=i;//记录下当前这个值的位置
//我当时就卡在这个地方了,当初记录的是这个值本身,结果还是要记录值的位置,还因此开了四个数组,还卡在什么莫名的地方调不出来,真的是。。。。
           while (a[f1[head1]]-a[f2[head2]]>k)如果当前最大最小之差已经不符合条件了,换区间
           {
              if (f1[head1]<f2[head2]) head1+=1,tot=f1[head1-1];
              else head2+=1,tot=f2[head2-1];
        }
        ans=max(i-tot,ans);
    }
    printf("%d",ans);
    return 0;
}