zoukankan      html  css  js  c++  java
  • hdu 3530 单调队列最值

    /**
    HDU 3530  单调队列的应用
    题意:
         给定一段序列,求出最长的一段子序列使得该子序列中最大最小只差x满足m<=x<=k。
    解题思路:
         建立两个单调队列分别递增和递减维护(头尾删除,只有尾可插入)
         Max - Min 为两个队列的队首之差while(Max-Min>K) 看哪个的队首元素比较前就移动谁的
         最后求长度时,需要先记录上一次的被淘汰的最值位置last ,这样[last+1,i]即为满足条件的连续子序列了
    i - last
    */
    #include <stdio.h>
    #include <iostream>
    #include <string.h>
    #include <algorithm>
    using namespace std;
    const int N=100005;
    int q_max[N],q_min[N];//递增,递减
    int a[N],n,m,k;
    int main()
    {
        while(~scanf("%d%d%d",&n,&m,&k))
        {
            for(int i=1;i<=n;i++)
                scanf("%d",&a[i]);
            int head_min=0,head_max=0,tail_min=0,tail_max=0;
            int left1=0,left2=0;
            int maxx=0;
            for(int i=1;i<=n;i++)
            {
                while(head_min<tail_min&&a[q_min[tail_min-1]]<=a[i])
                    tail_min--;
                while(head_max<tail_max&&a[q_max[tail_max-1]]>=a[i])
                    tail_max--;
                q_max[tail_max++]=q_min[tail_min++]=i;
               /* printf("***%d 递减、递增***
    ",i);
                for(int j=head_min;j<tail_min;j++)
                       printf("%d ",a[q_min[j]]);
                printf("
    ");
                for(int j=head_max;j<tail_max;j++)
                       printf("%d ",a[q_max[j]]);
                printf("
    ");*/
                while(a[q_min[head_min]]-a[q_max[head_max]]>k)
                {
                    if(q_min[head_min]<q_max[head_max])
                          left1=q_min[head_min++];
                    else
                          left2=q_max[head_max++];
                }
                if(a[q_min[head_min]]-a[q_max[head_max]]>=m)
                      maxx=max(maxx,i-max(left1,left2));
            }
            printf("%d
    ",maxx);
        }
        return 0;
    }
    /*
    5 2 3
    1 -1 2 -6 5
    5 1 3
    1 2 3 4 5
    6 0 0
    -1 0 2 1 125 -5
    */
    #include<bits/stdc++.h>
    using namespace std;
    const int maxn = 1e5+5;
    int a[maxn], q1[maxn], q2[maxn];
    int main()
    {
        int n, m, k;
        while(cin>>n>>m>>k) {
            for(int i = 0; i<n; i++) {
                scanf("%d", &a[i]);
            }
            int st1 = 0, st2 = 0, ed1 = 0, ed2 = 0, ans = 0, now = 0;
            for(int i = 0; i<n; i++) {
                while(st1<ed1&&a[q1[ed1-1]]<a[i])       //q1维护一个单调递减的数列,这样队头元素是最大值, 第二个是第二大的值
                    ed1--;
                while(st2<ed2&&a[q2[ed2-1]]>a[i])       //q2维护一个单调递增的数列, 队头是最小值。
                    ed2--;
                q1[ed1++] = q2[ed2++] = i;              
                while(st1<ed1&&st2<ed2&&a[q1[st1]]-a[q2[st2]]>k) {      //如果最大值-最小值大于k
                    if(q1[st1]<q2[st2]) {
                        now = q1[st1++]+1;                 //如果最大值在序列中的位置小于最小值
                    } else {
                        now = q2[st2++]+1;
                    }
                }
                if(st1<ed1&&st2<ed2&&a[q1[st1]]-a[q2[st2]]>=m) {
                    ans = max(ans, i-now+1);                //只有最大值-最小值大于等于m的时候才更新ans
                }
            }
            cout<<ans<<endl;
        }
    }
  • 相关阅读:
    纪伯伦:我曾七次鄙视我的灵魂
    字典和集合
    元组
    列表
    字符串
    数值类型
    内置函数了解一下
    了解Python
    centos7安装mysql数据库
    xenserver 上传centos6.8镜像
  • 原文地址:https://www.cnblogs.com/Aragaki/p/7647121.html
Copyright © 2011-2022 走看看