传送门

题意:

  给出一个序列,求最长的连续子序列,使得 m ≤ Max-Min ≤ k

我的理解:

  定义数组 a[] 存储输入的 n 个数;

  定义两个双端队列:

  deque<int >qMax,qMin;

  qMax : 维护前 i 个数的最大值(非递增序列);

  qMin : 维护前 i 个数的最小值(非递增序列);

 for(int i=;i <= n;++i)
{
///注意此处用了'=',也就是说,队列中的所有数都互异
while(!qMax.empty() && a[qMax.back()] <= a[i])
qMax.pop_back();///保证qMax递减
qMax.push_back(i);
while(!qMin.empty() && a[qMin.back()] >= a[i])
qMin.pop_back();///保证qMin递增
qMin.push_back(i);
}

  例如:

    1  2  3  4  5  6

  val:  9  6  5  1  2  3

  i = 6 时的队列情况(此处队列中维护的是值,便于理解):

    qMax : {9,6,5,3};

    qMin : {1,2,3};

  假设来到 i 位置(队列维护下标):

  qMax : { φ123,...,i };(下标递增,下标对应的值递减)

  qMin : { ω123,....,i }:(下标递增,下标对应的值递增)

  

    (φ123,...ω12互不相同,当然 i 除外)

    (qMax.val ≥ qMin.val,下标对应的值)

  下面看看队列的操作(pos初始为1):

 while(a[qMax.front()]-a[qMin.front()] > k)
{
if(qMax.front() < qMin.front())
{
pos=qMax.front()+;
qMax.pop_front();
}
else
{
pos=qMin.front()+;
qMin.pop_front();
}
}
if(a[qMax.front()]-a[qMin.front()] >= m)
ans=max(ans,i-pos+);

  首先判断 qMax.front() 对应的值(假设为 a[φ1]) 与 qMin.front() 对应的值(假设为 a[ω1])做差是否大于 k;

  如果大于,那么,如何使差值变小呢?

  操作①qMax.pop_front(),(φ1 -> φ2)下一位对应的值更小

  操作②qMin.pop_front(),(ω-> ω2)下一位对应的值更大

  操作①②都可以使他们两者的差值变小,那么,到底该用哪个操作呢?

  答案:谁的下标小,弹出谁,并且,所有的出队操作是不可能使队列为空的,因为两个队列中都有a[ i ]这个元素;

  为什么要这么做呢?

  假设不这么做,那么就是谁的下标大,弹出谁,假设 φ> ω

  那么,就需要弹出φ1 ,那么,包含当前最值的区间为[ ω12],但是,φ1 也在其中,最大值就不该是a[φ1 ]而应该是a[φ2];

  所以,谁的下标小,弹出谁;

  pos作用又是啥呢?

  找到包含 a[ i ] 的,并且满足条件的最大的区间,也就是[pos,i]是包含a[i]的最大的区间;

  那,为什么pos=front()+1就一定对呢?

  假设当前弹出的是φ,也就是说a[φ1]-a[ω1] > t,假设 a[φ2]-a[ω1] ≤ t;

  那么,a[pos]-a[ω1] ≤ t;

  因为a[pos] ≤ a[φ2],在 φ满足条件的情况下,pos一定满足条件,且是满足条件的最大的区间(φ1不满足);

  为什么不用判断其是否 ≥ m 呢?

  因为操作①②都是使差值减小,只有可能在后面的更新队列的操作中使其差值增大;

AC代码:

 #include<iostream>
#include<cstdio>
#include<deque>
using namespace std;
const int maxn=1e5+; int n,m,k;
int a[maxn];
deque<int >qMax,qMin; int Solve()
{
qMax.clear();
qMin.clear(); int ans=;
int pos=;
for(int i=;i <= n;++i)
{
///注意此处用了'=',也就是说,队列中的所有数都互异
///不加'='也行,不影响答案,因为在弹出操作时,qMax,qMin都将等于a[i]的给去了
///那么,a[i]本身是不会更新pos的值
///就算是队列末尾有重复的a[i]也不会更新pos,这就保证了pos的正确性
///[pos,i]是包含a[i]的最大的区间
while(!qMax.empty() && a[qMax.back()] <= a[i])
qMax.pop_back();
qMax.push_back(i);
while(!qMin.empty() && a[qMin.back()] >= a[i])
qMin.pop_back();
qMin.push_back(i); while(a[qMax.front()]-a[qMin.front()] > k)///最坏的情况是最后两个队列只剩下a[i]
{
if(qMax.front() < qMin.front())
{
pos=qMax.front()+;
qMax.pop_front();
}
else
{
pos=qMin.front()+;
qMin.pop_front();
}
}
if(a[qMax.front()]-a[qMin.front()] >= m)
ans=max(ans,i-pos+);///判断[pos,i]区间是否更新ans
}
return ans;
}
int main()
{
while(~scanf("%d%d%d",&n,&m,&k))
{
for(int i=;i <= n;++i)
scanf("%d",a+i);
printf("%d\n",Solve());
}
return ;
}

hdu 3530 "Subsequence" (单调队列)的更多相关文章

  1. HDU - 3530 Subsequence (单调队列)

    Subsequence Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total ...

  2. hdu 3530 Subsequence 单调队列

    题目链接 题目给出n个数, 一个下界m, 一个上界k, 让你求出最长的一段序列, 满足这段序列中的最大的数-最小的数<=k&&>=m, 输出这段长度. 可以维护两个队列, ...

  3. 【单调队列+尺取】HDU 3530 Subsequence

    acm.hdu.edu.cn/showproblem.php?pid=3530 [题意] 给定一个长度为n的序列,问这个序列满足最大值和最小值的差在[m,k]的范围内的最长子区间是多长? [思路] 对 ...

  4. HDU 3530 Subsequence(单调队列)

    传送门 Description There is a sequence of integers. Your task is to find the longest subsequence that s ...

  5. hdu 3530 Subsequence

    题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=3530 Subsequence Description There is a sequence of i ...

  6. HDU 3401 Trade(单调队列优化)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3401 题意:炒股.第i天买入一股的价钱api,卖出一股的价钱bpi,最多买入asi股,最多卖出bsi股 ...

  7. Hdu 3410 【单调队列】.cpp

    题意: 给出一个数组,问你对于第i个数,从最后一个比它大的数到它之间比它小的数中最大的那个数的下标,以及它右边到第一个比它大的数中比它小的数中最大的那一个数的下标<下标从1开始>. eg: ...

  8. HDU 5749 Colmerauer 单调队列+暴力贡献

    BestCoder Round #84   1003 分析:(先奉上zimpha巨官方题解) 感悟:看到题解单调队列,秒懂如何处理每个点的范围,但是题解的一句算贡献让我纠结半天 已知一个点的up,do ...

  9. HDU 5289 Assignment(单调队列)

    题意:给T足数据,然后每组一个n和k,表示n个数,k表示最大同意的能力差,接下来n个数表示n个人的能力,求能力差在k之内的区间有几个 分析:维护一个区间的最大值和最小值,使得他们的差小于k,于是採用单 ...

随机推荐

  1. django学习自修第一天【简介】

    1. MVC框架 MVC框架的核心思想是解耦,降低各功能之间的耦合性,方便重构代码 (1)低耦合,高内聚 (2)高可扩展性 (3)向后兼容 2. MVT框架 V(视图):核心处理,接受请求,调用模型获 ...

  2. qtp 自动货测试桌面程序-笔记(使用参数 parameters)

    dtGlobalSheet:运行整个test时候使用的参数(心得:可以将公共使用的测试数据放于全局表格中,所有action脚本都可以使用同一个数据,如供应商.客户.商品) dtActionSheet: ...

  3. 一、纯css实现顶部进度条随滚动条滚动

    一.效果图 二.直接复制粘贴 <!DOCTYPE html> <html lang="en"> <head> <meta charset= ...

  4. EChart.js 笔记一

    一直对数据可视化比较感兴趣,当年 Alibaba 年报晚会上的大屏显示可谓是技惊四座,够震撼,将数据之美展现得淋漓尽致. 国内的前端数据可视化插件中,echart.js 算是热度很高的,也容易上手,算 ...

  5. 比特币中的Base58 编码

    base58和base64一样是一种二进制转可视字符串的算法,主要用来转换大整数值.区别是,转换出来的字符串,去除了几个看起来会产生歧义的字符,如 0 (零), O (大写字母O), I (大写的字母 ...

  6. ImportError: No module named google.protobuf.internal

    下载: protobuf-3.3.0 设置路径:export PYTHONPATH=/gruntdata/lihaiyang/local/protobuf-3.3.0/python:$PYTHONPA ...

  7. StringBuffer作为参数传递的问题

    public class Foo {2.   public static void main (String [] args)  {3.      StringBuffer a = new Strin ...

  8. Git——入门操作加创建账号【三】

    创建账号 GitHub https://github.com/ 码云 https://gitee.com/ 无论是github还是码云,创建账号都是非常简单快捷的,大家可以自行选择创建下,不过建议最好 ...

  9. P1601 A+B Problem(高精)

    原题链接 https://www.luogu.org/problemnew/show/P1601 这个题提示的很清楚,并非简单的A+B,单纯的long  long型也不行(不要被样例所迷惑).因为lo ...

  10. Codeforces997D Cycles in product 【FFT】【树形DP】

    题目大意: 给两个树,求环的个数. 题目分析: 出题人摆错题号系列. 通过画图很容易就能想到把新图拆在两个树上,在树上游走成环. 考虑DP状态F,G,T.F表示最终答案,T表示儿子不考虑父亲,G表示父 ...