为了方便,令$a_{0}=a_{n+1}=\infty$,另外$a_{i}$是两两不同的

记$L_{x}$和$R_{x}$分别为$x$左右两侧第一个比$a_{x}$大的元素位置,可以$o(n)$预处理出来

记$d(x,y)$表示从$x$到$y$的最短路(其中$x\le y$),若不存在$x$到$y$的路径则记$d(x,y)=\infty$

性质:

对于$1\le x<y\le n$(其中$a_{x}<a_{y}$)和$\forall a_{x}\le d\le a_{y}$,令$l=\max_{k\le x,a_{k}\ge d}k$和$r=\min_{k\ge x,a_{k}\ge d}k$,则$x$到$y$的路径上必然经过$l$或$r$,也即$d(x,y)=\min(d(x,l)+d(l,y),d(x,r)+d(r,y))$

利用这条性质,我们可以得到以下结论——

结论1:对于$1\le x<y\le n$,若$\exists x\le i<y,a_{y}<a_{i}$,则不存在$x$到$y$的路径

证明:取性质中$(x,y,d)=(x,y,a_{y})$,显然$l,r\ne y$,即$a_{l},a_{r}>a_{y}$,也即$d(l,y)=d(r,y)=\infty$,代入式子中即可得$d(x,y)=\infty$,不存在$x$到$y$的路径

(事实上,这也是充分条件)

结论2:

对于$1\le x<y\le n$,若$\forall x<i\le y,a_{i}<a_{x}$, 则$\forall y<z$且$a_{x}<a_{z},d(x,z)\le d(y,z)$

对于$1\le x<y\le n$,若$\forall x\le i<y,a_{i}<a_{y}$,则$\forall y<z$且$a_{y}<a_{z},d(x,z)\ge d(y,z)$

证明:

(两个情况是类似的,以下只证明第一个情况)

取性质中$(x,y,d)=(y,z,a_{x})$,显然$l=x$且$r=R_{x}$(且$y\ne l,r$),因此$y$到$l$和$r$至少要一步,而$x$到$l$和$r$只需要0或1步,即$d(x,l)=0<d(y,l)$且$d(x,r)=1\le d(y,l)$

因此,即有
$$
d(x,z)\le \min(d(x,l)+d(l,z),d(x,r)+d(r,z))\le \min(d(y,l)+d(l,z),d(y,r)+d(r,z))=d(y,z)
$$

下面,考虑如何求$d(x,y)$(其中$x<y$):

不妨假设$a_{L_{x}}<a_{R_{x}}$,显然$\forall L_{x}\le i<R_{x},a_{i}<a_{R_{x}}$,接下来分类讨论:

1.若$a_{R_{x}}\le a_{y}$,根据结论2即有$d(R_{x},y)\le d(L_{x},y)$,贪心移动到$R_{x}$

2.若$a_{L_{x}}\le a_{y}<a_{R_{x}}$,显然不能移动到$R_{x}$,只能移动到$L_{x}$

3.若$a_{y}<a_{L_{x}}$,显然$x$不能再移动

重复上述过程,最后第3种情况时若$x=y$即得到最短路,否则无解

再用倍增来优化这个贪心,即可$o(\log n)$求出$x$到$y$的最短路

下面,考虑如何求$\min_{x_{1}\le x\le x_{2}}d(x,y)$(其中$x_{1}\le x_{2}<y$):

令$p=L_{y}$,根据结论1显然起点$x>p$(否则即存在$a_{y}<a_{p}$),那么若$x_{2}\le p$即无解

令$a_{q}$为区间$[\max(p+1,x_{1}),x_{2}]$的最大值,那么$\forall x\in [\max(p+1,x_{1}),q)$,显然$\forall x\le i<q,a_{i}<a_{q}$且$a_{q}<a_{y}$($x\in (q,x_{2}]$同理),根据结论2即可得$d(q,y)$即为答案

关于如何求$d(q,y)$前面已经叙述,复杂度为$o(\log n)$

下面,考虑如何求$\min_{x_{1}\le x\le x_{2},y_{1}\le y\le y_{2}}d(x,y)$(其中$x_{1}\le x_{2}<y_{1}\le y_{2}$):

令$a_{p_{1}}$为区间$[x_{2},y_{1})$的最大值和$q_{1}=R_{p_{1}}$,根据结论1显然终点$y>q_{1}$(否则即存在$a_{y}<a_{p_{1}}$),那么若$q_{1}>y_{2}$即无解,因此不妨设$y_{1}\le q_{1}\le y_{2}$

再令$p_{2}=L_{q_{1}}$和$q_{2}=R_{p_{2}}$,则答案为$\min(\min_{x_{1}\le x\le x_{2}}d(x,q_{1}),\min_{x_{1}\le x\le x_{2}}d(x,q_{2}))$(特别的,若$q_{2}>y_{2}$则后项定义为$\infty$)

关于这个结论,对$p_{2}$分类讨论:

1.若$p_{2}<x_{1}$,取性质中$(x,y,d)=(x,y,a_{q_{1}})$,显然$l=p_{2}$且$r=q_{1}$

当我们到达$l$后,若$q_{2}=R_{l}$不在$[y_{1},y_{2}]$中即无解,否则只需要1步即可到达$q_{2}$

当我们到达$r$后,即已经在$q_{1}=r$

2.若$p_{2}\ge x_{1}$(显然$p_{2}\le x_{2}$),若$q_{2}$在$[y_{1},y_{2}]$中则取$x=p_{2}$和$y=q_{2}$即可(仍以$y_{2}$为终点),否则必然有起点$x>p_{2}$(否则存在$a_{y}<a_{p_{2}}$),之后与第1种情况相同

关于如何求$\min_{x_{1}\le x\le x_{2}}d(x,q)$前面已经叙述,复杂度为$o(\log n)$

最终,总复杂度为$o(n\log n)$,可以通过

  1. 1 #include<bits/stdc++.h>
  2. 2 using namespace std;
  3. 3 #define N 200005
  4. 4 #define oo 0x3f3f3f3f
  5. 5 #define L (k<<1)
  6. 6 #define R (L+1)
  7. 7 #define mid (l+r>>1)
  8. 8 int n,a[N],st[N],l[N],r[N],id[N],mn[N][21],mx[N][21],f[N<<2];
  9. 9 bool cmp(int x,int y){
  10. 10 return a[x]>a[y];
  11. 11 }
  12. 12 int get_max(int x,int y){
  13. 13 if (a[x]>a[y])return x;
  14. 14 return y;
  15. 15 }
  16. 16 void build(int k,int l,int r){
  17. 17 if (l==r){
  18. 18 f[k]=l;
  19. 19 return;
  20. 20 }
  21. 21 build(L,l,mid);
  22. 22 build(R,mid+1,r);
  23. 23 f[k]=get_max(f[L],f[R]);
  24. 24 }
  25. 25 int query(int k,int l,int r,int x,int y){
  26. 26 if ((l>y)||(x>r))return n+1;
  27. 27 if ((x<=l)&&(r<=y))return f[k];
  28. 28 return get_max(query(L,l,mid,x,y),query(R,mid+1,r,x,y));
  29. 29 }
  30. 30 void init(int nn,vector<int>v){
  31. 31 n=nn;
  32. 32 a[0]=oo;
  33. 33 for(int i=1;i<=n;i++)a[i]=v[i-1];
  34. 34 for(int i=1;i<=n;i++){
  35. 35 while ((st[0])&&(a[st[st[0]]]<a[i]))st[0]--;
  36. 36 l[i]=st[st[0]];
  37. 37 st[++st[0]]=i;
  38. 38 }
  39. 39 st[0]=0;
  40. 40 for(int i=n;i;i--){
  41. 41 while ((st[0])&&(a[st[st[0]]]<a[i]))st[0]--;
  42. 42 r[i]=st[st[0]];
  43. 43 st[++st[0]]=i;
  44. 44 }
  45. 45 for(int i=1;i<=n;i++){
  46. 46 id[i]=i;
  47. 47 mn[i][0]=l[i],mx[i][0]=r[i];
  48. 48 if (a[mn[i][0]]>a[mx[i][0]])swap(mn[i][0],mx[i][0]);
  49. 49 }
  50. 50 sort(id+1,id+n+1,cmp);
  51. 51 for(int i=1;i<=n;i++){
  52. 52 int x=id[i];
  53. 53 for(int j=1;j<=20;j++){
  54. 54 mn[x][j]=mn[mn[x][j-1]][j-1];
  55. 55 mx[x][j]=mx[mx[x][j-1]][j-1];
  56. 56 }
  57. 57 }
  58. 58 build(1,1,n);
  59. 59 }
  60. 60 int minimum_jumps(int x,int y){
  61. 61 int ans=0;
  62. 62 for(int i=20;i>=0;i--)
  63. 63 if (a[mx[x][i]]<=a[y]){
  64. 64 x=mx[x][i];
  65. 65 ans+=(1<<i);
  66. 66 }
  67. 67 for(int i=20;i>=0;i--)
  68. 68 if (a[mn[x][i]]<=a[y]){
  69. 69 x=mn[x][i];
  70. 70 ans+=(1<<i);
  71. 71 }
  72. 72 if (x!=y)ans=oo;
  73. 73 return ans;
  74. 74 }
  75. 75 int minimum_jumps(int x1,int x2,int y){
  76. 76 int p=l[y];
  77. 77 if (x2<=p)return oo;
  78. 78 int q=query(1,1,n,max(p+1,x1),x2);
  79. 79 return minimum_jumps(q,y);
  80. 80 }
  81. 81 int minimum_jumps(int x1,int x2,int y1,int y2){
  82. 82 x1++,x2++,y1++,y2++;
  83. 83 int p1=query(1,1,n,x2,y1-1),q1=r[p1],ans=oo;
  84. 84 if ((q1)&&(q1<=y2)){
  85. 85 ans=minimum_jumps(x1,x2,q1);
  86. 86 int p2=l[q1],q2=r[p2];
  87. 87 if ((q2)&&(q2<=y2))ans=min(ans,minimum_jumps(x1,x2,q2));
  88. 88 }
  89. 89 if (ans==oo)ans=-1;
  90. 90 return ans;
  91. 91 }

[luogu7599]雨林跳跃的更多相关文章

  1. P7599-[APIO2021]雨林跳跃【二分,倍增,ST表】

    正题 题目链接:https://www.luogu.com.cn/problem/P7599 题目大意 \(n\)棵树,在某棵树上时可以选择向左右两边第一棵比它高的树跳,现在\(q\)次询问从\([A ...

  2. 跳跃的舞者,舞蹈链(Dancing Links)算法——求解精确覆盖问题

    精确覆盖问题的定义:给定一个由0-1组成的矩阵,是否能找到一个行的集合,使得集合中每一列都恰好包含一个1 例如:如下的矩阵 就包含了这样一个集合(第1.4.5行) 如何利用给定的矩阵求出相应的行的集合 ...

  3. [LeetCode] Jump Game II 跳跃游戏之二

    Given an array of non-negative integers, you are initially positioned at the first index of the arra ...

  4. AC日记——有趣的跳跃 openjudge 1.6 07

    07:有趣的跳跃 总时间限制:  1000ms 内存限制:  65536kB 描述 一个长度为n(n>0)的序列中存在“有趣的跳跃”当前仅当相邻元素的差的绝对值经过排序后正好是从1到(n-1). ...

  5. 青瓷引擎之纯JavaScript打造HTML5游戏第二弹——《跳跃的方块》Part 10(排行榜界面&界面管理)

    继上一次介绍了<神奇的六边形>的完整游戏开发流程后(可点击这里查看),这次将为大家介绍另外一款魔性游戏<跳跃的方块>的完整开发流程. (点击图片可进入游戏体验) 因内容太多,为 ...

  6. SQLServer2012自增列值跳跃的问题

    2012引入的新特性,重启之后会出现值跳跃的问题,如: 解决的方案: 1.使用序列(Sequence),2012引入的和Oracle一样的特性. 2.更改SQLServer启动服务的启动参数,增加[- ...

  7. Unity手游之路<十>自动寻路Navmesh之跳跃,攀爬,斜坡

    http://blog.csdn.net/janeky/article/details/17598113 在之前的几篇Blog总,我们已经系统学习了自动寻路插件Navmesh的相关概念和细节.然而,如 ...

  8. SQL Server 2012 自动增长列,值跳跃问题

    介绍 从 SQL Server 2012 版本开始, 当SQL Server 实例重启之后,表格的自动增长列的值会发生跳跃,而具体的跳跃值的大小是根据增长列的数据类型而定的.如果数据类型是 整型(in ...

  9. 跳跃表Skip List的原理和实现

    >>二分查找和AVL树查找 二分查找要求元素可以随机访问,所以决定了需要把元素存储在连续内存.这样查找确实很快,但是插入和删除元素的时候,为了保证元素的有序性,就需要大量的移动元素了.如果 ...

随机推荐

  1. mapboxgl 纠偏百度地图

    缘起 之前分享了mapboxgl 互联网地图纠偏插件,插件当时只集成了高德地图. 文章发布后,有小伙伴在后台留言,希望插件也能支持百度地图. 刚好国庆假期有时间就研究了一下. 插件加载瓦片原理 首先, ...

  2. java 从零开始手写 RPC (07)-timeout 超时处理

    <过时不候> 最漫长的莫过于等待 我们不可能永远等一个人 就像请求 永远等待响应 超时处理 java 从零开始手写 RPC (01) 基于 socket 实现 java 从零开始手写 RP ...

  3. ThreadLocalRandom类原理分析

    1.Random类及其局限性 public int nextInt(int bound) { if (bound <= 0) throw new IllegalArgumentException ...

  4. 【数据结构与算法Python版学习笔记】图——骑士周游问题 深度优先搜索

    骑士周游问题 概念 在一个国际象棋棋盘上, 一个棋子"马"(骑士) , 按照"马走日"的规则, 从一个格子出发, 要走遍所有棋盘格恰好一次.把一个这样的走棋序列 ...

  5. Coursera Deep Learning笔记 序列模型(二)NLP & Word Embeddings(自然语言处理与词嵌入)

    参考 1. Word Representation 之前介绍用词汇表表示单词,使用one-hot 向量表示词,缺点:它使每个词孤立起来,使得算法对相关词的泛化能力不强. 从上图可以看出相似的单词分布距 ...

  6. 注解,@Qualifier+@Autowired 和 @Resource

    摘要: 项目中,对于AOP的使用,就是通过用注解来注入的. 更改之前的注解,是使用:@Qualifier+@Autowired   但是,通过这样注解,在项目启动阶段,需要自动扫描的过程是非常缓慢的, ...

  7. Alpha-技术规格说明书

    项目 内容 这个作业属于哪个课程 2021春季软件工程(罗杰 任健) 这个作业的要求在哪里 团队项目-计划-功能规格说明书 一.架构与技术栈 1.整体架构 本项目的整体架构如上图所示.下面我们将对涉及 ...

  8. 第3次 Beta Scrum Meeting

    本次会议为Beta阶段第3次Scrum Meeting会议 会议概要 会议时间:2021年6月2日 会议地点:「腾讯会议」线上进行 会议时长:0.5小时 会议内容简介:对完成工作进行阶段性汇报:对下一 ...

  9. 洛谷 P2252 [SHOI2002]取石子游戏|【模板】威佐夫博弈

    链接: P2252 [SHOI2002]取石子游戏|[模板]威佐夫博弈 前言: 第一眼大水题,第二眼努力思考,第 N 眼我是大水逼. 题意: 不看题目标题都应该能看出来是取石子类的博弈论. 有两堆石子 ...

  10. MyBatis源码分析(七):动态代理(Mybatis核心机制)

    一.动态代理 动态代理是一种比较高级的代理模式,它的典型应用就是Spring AOP. 在传统的动态代理模式中,客户端通过ProxySubject调用RealSubject类的request( )方法 ...