【POI2010】BZOJ2096 pilots

来源:互联网 发布:怎么开淘宝网店及货源 编辑:程序博客网 时间:2024/05/21 11:36

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 输出:最大的字串长度。

从左往右扫描的时候,最大值不会变小,最小值不会变大,所以现在被舍弃的、太大的最大值和太小的最小值,以后也不会被用到。可以考虑单调队列。
用两个队列分别维护有用的最大值和最小值,其中最大值序列递减,最小值序列递增,保证每个元素都是从他往后整个序列的最大、小值。向右扫描的时候,首先在队尾出队并将该点入队使之仍然满足递增、递减性质。然后在队头出队使之满足差不超过k的性质,具体做法是将两个队头较靠前的元素出队,并且更新答案【左端点】所在的位置。最后更新答案。
注意细节:
1.最开始答案的左端点为1。
2.只有当扫描到的元素严格大于、小于队尾时才将队尾出队,因为等于时队尾比当前元素更优。

#include<cstdio>#include<cstring>int min(int x,int y){    return x<y?x:y;}int max(int x,int y){    return x>y?x:y;}int q_min[3000010],q_max[3000010],a[3000010];int main(){    int i,j,k,m,n,p,q,x,y,z,h_max,t_max,h_min,t_min,ans=0;    scanf("%d%d",&k,&n);    for (i=1;i<=n;i++)      scanf("%d",&a[i]);    h_max=h_min=1;    t_max=t_min=0;    p=1;    for (i=1;i<=n;i++)    {        while (h_max<=t_max&&a[q_max[t_max]]<a[i]) t_max--;        q_max[++t_max]=i;        while (h_min<=t_min&&a[q_min[t_min]]>a[i]) t_min--;        q_min[++t_min]=i;        while (a[q_max[h_max]]-a[q_min[h_min]]>k)        {            if (q_max[h_max]<q_min[h_min])            {                p=q_max[h_max]+1;                h_max++;            }            else            {                p=q_min[h_min]+1;                h_min++;            }        }        ans=max(ans,i-p+1);    }    printf("%d\n",ans);}
0 0
原创粉丝点击