首页 > 其他 > 详细

HDU-3530Subsequence (单调队列)

时间:2020-07-08 13:14:58      阅读:71      评论:0      收藏:0      [点我收藏+]

题目链接: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\n",ans);
    }
    return 0;
}

 

HDU-3530Subsequence (单调队列)

原文:https://www.cnblogs.com/lonely-wind-/p/13266333.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!