acm.hdu.edu.cn/showproblem.php?pid=3530

【题意】

  • 给定一个长度为n的序列,问这个序列满足最大值和最小值的差在[m,k]的范围内的最长子区间是多长?

【思路】

  • 对于序列中特定的位置j,我们固定右端j考察左端i,发现[i,j]内的最大值随i的增大而非严格递减
  • 对于序列中特定的位置j,我们固定右端j考察左端i,发现[i,j]内的最小值随i的增大而非严格递增
  • 所以[i,j]内最大值与最小值的差随i的增大而递减
  • 对于序列中特定的位置i,我们固定左端i考察右端j,发现[i,j]内的最大值随j的增大而非严格递增
  • 对于序列中特定的位置i,我们固定左端i考察右端j,发现[i,j]内的最小值随j的增大而非严格递减
  • 所以[i,j]内最大值与最小值的差随i的增大而递增
  • 所以我们可以尺取,即如位置j对应的左端为l,那么i+1的从l以后找
  • 两个单调队列mx和mn分别维护最大值和最小值
  • mx中存放的是a中数的下标(单调递增),对应的a中的数是单调递减
  • mn中存放的是a中数的下标(单调递增),对应的a中的数是单调递增
  • 当a[mx[lx]]-a[mn[ln]]>k时,出队列的是mx[lx]和mn[ln]较小的一个,这样才能保证最长子区间
  • 当a[mx[lx]]-a[mn[ln]]<m时,不需做任何操作,因为差是随左端点的增大而递减的,如果a[mx[lx]]-a[mn[ln]]<m,只能不更新ans

【AC】

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. typedef long long ll;
  4. int n,m,k;
  5. const int maxn=1e5+;
  6. int a[maxn];
  7. int mx[maxn],lx,rx;
  8. int mn[maxn],ln,rn;
  9. int l,ans;
  10. int main()
  11. {
  12. while(~scanf("%d%d%d",&n,&m,&k))
  13. {
  14. for(int i=;i<=n;i++) scanf("%d",&a[i]);
  15. lx=ln=;rx=rn=;l=;
  16. ans=;
  17. for(int i=;i<=n;i++)
  18. {
  19. while(lx<=rx&&a[mx[rx]]<=a[i]) rx--;
  20. mx[++rx]=i;
  21. while(ln<=rn&&a[mn[rn]]>=a[i]) rn--;
  22. mn[++rn]=i;
  23. while(lx<=rx&&ln<=rn&&a[mx[lx]]-a[mn[ln]]>k)
  24. {
  25. if(mx[lx]>=mn[ln])
  26. {
  27. l=mn[ln];
  28. ln++;
  29. }
  30. else
  31. {
  32. l=mx[lx];
  33. lx++;
  34. }
  35. }
  36. if(a[mx[lx]]-a[mn[ln]]>=m)
  37. ans=max(ans,i-l);
  38. }
  39. printf("%d\n",ans);
  40. }
  41. return ;
  42. }

单调队列+尺取

【疑问】

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. typedef long long ll;
  4. int n,m,k;
  5. const int maxn=1e5+;
  6. int a[maxn];
  7. int mx[maxn];
  8. int mn[maxn];
  9. struct node
  10. {
  11. int x;
  12. int pos;
  13. }q[maxn];
  14. bool judge(int mid)
  15. {
  16. memset(q,,sizeof(q));
  17. memset(mx,,sizeof(mx));
  18. memset(mn,,sizeof(mn));
  19. int head=,tail=;
  20. for(int i=;i<=n;i++)
  21. {
  22. while(tail>=head&&q[tail].x<a[i]) tail--;
  23. q[++tail].x=a[i];q[tail].pos=i;
  24. while(q[head].pos<=i-mid) head++;
  25. if(i>=mid) mx[i]=q[head].x;
  26. }
  27.  
  28. head=,tail=;
  29. for(int i=;i<=n;i++)
  30. {
  31. while(tail>=head&&q[tail].x>a[i]) tail--;
  32. q[++tail].x=a[i];q[tail].pos=i;
  33. while(q[head].pos<=i-mid) head++;
  34. if(i>=mid) mn[i]=q[head].x;
  35. }
  36. for(int i=mid;i<=n;i++)
  37. {
  38. if(mx[i]-mn[i]>=m&&mx[i]-mn[i]<=k)
  39. {
  40. return true;
  41. }
  42. }
  43. return false;
  44. }
  45. int main()
  46. {
  47. while(scanf("%d%d%d",&n,&m,&k)!=EOF)
  48. {
  49. for(int i=;i<=n;i++)
  50. {
  51. scanf("%d",&a[i]);
  52. }
  53. int l=,r=n;
  54. while(l<=r)
  55. {
  56. int mid=(l+r)>>;
  57. if(judge(mid))
  58. {
  59. l=mid+;
  60. }
  61. else
  62. {
  63. r=mid-;
  64. }
  65. }
  66. printf("%d\n",l-);
  67. }
  68. return ;
  69. }

WA

不知道这个二分答案,然后用单调队列判断可行性为啥是挂的orz,我感觉没错.....希望哪位仁兄看到了帮忙指点一下,小弟不尽感激~

【单调队列+尺取】HDU 3530 Subsequence的更多相关文章

  1. 2019 牛客暑期多校 第三场 F Planting Trees (单调队列+尺取)

    题目:https://ac.nowcoder.com/acm/contest/883/F 题意:求一个矩阵最大面积,这个矩阵的要求是矩阵内最小值与最大值差值<=m 思路:首先我们仔细观察范围,我 ...

  2. HDU 3530 Subsequence(单调队列)

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

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

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

  4. hdu 3530 Subsequence

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

  5. bzoj1855: [Scoi2010]股票交易 单调队列优化dp ||HDU 3401

    这道题就是典型的单调队列优化dp了 很明显状态转移的方式有三种 1.前一天不买不卖: dp[i][j]=max(dp[i-1][j],dp[i][j]) 2.前i-W-1天买进一些股: dp[i][j ...

  6. hdu 3530 Subsequence 单调队列

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

  7. hdu 3530 "Subsequence" (单调队列)

    传送门 题意: 给出一个序列,求最长的连续子序列,使得 m ≤ Max-Min ≤ k 我的理解: 定义数组 a[] 存储输入的 n 个数: 定义两个双端队列: deque<int >qM ...

  8. [USACO13JAN] Cow Lineup (单调队列,尺取法)

    题目链接 Solution 尺取法板子,算是复习一波. 题中说最多删除 \(k\) 种,那么其实就是找一个颜色种类最多为 \(k+1\) 的区间; 统计一下其中最多的颜色出现次数. 然后直接尺取法,然 ...

  9. ACM-ICPC2018北京网络赛 80 Days(双端队列+尺取)

    题目4 : 80 Days 时间限制:1000ms 单点时限:1000ms 内存限制:256MB 描述 80 Days is an interesting game based on Jules Ve ...

随机推荐

  1. Ubuntu下Postgres安装与配置

    postgres8.4安装配置:1.安装postgres8.4~$ sudo apt-get install postgresql 2.修改超级管理员postgres密码:以系统用户运行psql~$ ...

  2. ajax报错问题的解决

    背景:用ajax与服务器页面进行交互 问题:XMLHttpRequest.status==0并且XMLHttpRequest.readyState==0并且textStatus==error 关于XM ...

  3. 在Windows笔记本上调试运行在iOS设备上的前端应用

    我在每天工作中需要在不同的移动设备上测试我们开发的前端应用是否正常工作,比如iOS设备和Android设备.我用的工作笔记本电脑又是Lenovo的,安装的是Windows操作系统. 有的时候一个开发好 ...

  4. HDU 4341 Gold miner (分组背包)

    先把线按照距离原点的距离排序,然后用叉积把在同一条直线上的点放在一起, 把在同一条线上的点中的前i个点当成一个点就转化成了分组背包. 写if(kas++) putchar('\n') 居然PE了,PE ...

  5. 一条SQL语句在MySQL中是如何执行的

    概览 本篇文章会分析下一个sql语句在mysql中的执行流程,包括sql的查询在mysql内部会怎么流转,sql语句的更新是怎么完成的. 一.mysql架构分析 mysql主要分为Server层和存储 ...

  6. go语音实战读后感——一

    1.第一个go程序: package main import ( "fmt" ) func main() { fmt.Println("Hello go") } ...

  7. VC-基础:VC中得到当前系统的时间和日期

    得到当前时间的方法一般都是得到从1900年0点0分到现在的秒数,然后转为年月日时分秒的形式得到当前的时间(时分秒).主要方法如下: 1)使用CRT函数 C++代码   ]; time_t nowtim ...

  8. myeclipse 导入项目时no projects are found to import解决办法

    myeclipse 识别一个工程需要.classpath与.project文件,一般无需提交SVN所以项目切下来的时候是没有这两个文件的. 方法1: 1) 在myeclipse中新建一个和你要导入的项 ...

  9. Java产生GUID

    /** * 产生GUID */public static final String generateGUID(){ UUID uuid = UUID.randomUUID(); return uuid ...

  10. PHP 头部utf-8

    只是自己用的一些存储,请各位看官大大勿怪. header("Content-Type: text/html;charset=utf-8"); 2019年04月10日