zoukankan      html  css  js  c++  java
  • HDU-3530Subsequence (单调队列)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3530

    题目大意:找到一个最大的子串,使得子串区间内最大值和最小值的差在L和R范围内。

    Sample Input

    5 0 0
    1 1 1 1 1
    5 0 3
    1 2 3 4 5

    Sample Output

    5
    4

    emmm,真的,看到subsequence ,这不是子序列嘛。。。既然是无序的,那么我们sort一下不就完事了嘛。。。。结果,题目没有描述清楚。。。实际上是子串。。。

    那么我们维护一下最大值和最小值就好了,本来RMQ也是可以做的。。。只不过会T。。所以只能想$O(n)$的做法了,那么很明显就是单调队列了。我们用一个队列来维护当前的最大值,一个来维护当前的最小值,这个很好办:

    while (head1<=tail1 && a[q1[tail1]]>a[i]) tail1--;
    q1[++tail1]=i;
    while (head2<=tail2 && a[q2[tail2]]<a[i]) tail2--;
    q2[++tail2]=i;

    接下来我们剔除掉差距过大的,差距太小不能剔除掉,因为后面可能还有大的,就会拉大差距,剔除过程如下:

    while (a[q2[head2]]-a[q1[head1]]>R) {
        if (q1[head1]<q2[head2]) st=q1[head1++];
        else st=q2[head2++];
    }

    需要值得注意的是,st得出来的是最后一个不合法的,要找到最小合法的id,那么可以将st+1,但没必要,因为后面计算长度的时候还要头减尾+1,所以我们可以直接将st当做尾巴,这样就省得多写几个+1了

    以下是AC代码:

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    using namespace std;
    
    const int mac=1e5+10;
    
    int a[mac],q1[mac],q2[mac];//上升序列,下降序列
    
    int main(int argc, char const *argv[])
    {
        int n,L,R;
        while (~scanf ("%d%d%d",&n,&L,&R)){
            for (int i=1; i<=n; i++)
                scanf ("%d",&a[i]);
            int head1=1,tail1=0,head2=1,tail2=0;
            int ans=0,st=0;
            for (int i=1; i<=n; i++){//从i开始最多能够往前拓展的最大长度
                while (head1<=tail1 && a[q1[tail1]]>a[i]) tail1--;
                q1[++tail1]=i;
                while (head2<=tail2 && a[q2[tail2]]<a[i]) tail2--;
                q2[++tail2]=i;
    
                while (a[q2[head2]]-a[q1[head1]]>R){
                    if (q1[head1]<q2[head2]) st=q1[head1++];
                    else st=q2[head2++];
                }
                if (a[q2[head2]]-a[q1[head1]]>=L && a[q2[head2]]-a[q1[head1]]<=R)
                    ans=max(ans,i-st);
            }
            printf("%d
    ",ans);
        }
        return 0;
    }
    路漫漫兮
  • 相关阅读:
    5.19 省选模拟赛 T1 小B的棋盘 双指针 性质
    5.15 省选模拟赛 容斥 生成函数 dp
    5.15 省选模拟赛 T1 点分治 FFT
    5.15 牛客挑战赛40 B 小V的序列 关于随机均摊分析 二进制
    luogu P4929 【模板】舞蹈链 DLX
    CF 878E Numbers on the blackboard 并查集 离线 贪心
    5.10 省选模拟赛 拍卖 博弈 dp
    5.12 省选模拟赛 T2 贪心 dp 搜索 差分
    5.10 省选模拟赛 tree 树形dp 逆元
    luogu P6088 [JSOI2015]字符串树 可持久化trie 线段树合并 树链剖分 trie树
  • 原文地址:https://www.cnblogs.com/lonely-wind-/p/13266333.html
Copyright © 2011-2022 走看看