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

    mybatis配置问题记录 org.apache.ibatis.binding.BindingException: Type interface com.xx.dao.UserDao(自己项目的文件) ...

  2. Flask聚合函数(基本聚合函数、分组聚合函数、去重聚合函数))

    Flask聚合函数 1.基本聚合函数(sun/count/max/min/avg) 使用聚合函数先导入:from sqlalchemy import func 使用方法: sun():func.sum ...

  3. MyBatis的框架设计

    1.MyBatis的框架设计 2.整体设计 2.1 总体流程 (1)加载配置并初始化       触发条件:加载配置文件 配置来源于两个地方,一处是配置文件,一处是Java代码的注解,将SQL的配置信 ...

  4. kafka应用讲解及应用场景(三)

    一. 验证 1.进入bin目录 cd bin 2.ls查看脚本 会发现下面有很多脚本文件,由于我是要创建一个topic所有直接打开kafka-topics.sh脚本查看命令 打开脚本后发现里面有很多命 ...

  5. Go语言核心36讲(Go语言进阶技术六)--学习笔记

    12 | 使用函数的正确姿势 在前几期文章中,我们分了几次,把 Go 语言自身提供的,所有集合类的数据类型都讲了一遍,额外还讲了标准库的container包中的几个类型. 在几乎所有主流的编程语言中, ...

  6. Coursera Deep Learning笔记 改善深层神经网络:优化算法

    笔记:Andrew Ng's Deeping Learning视频 摘抄:https://xienaoban.github.io/posts/58457.html 本章介绍了优化算法,让神经网络运行的 ...

  7. 万里阳光号Srcum Metting博客汇总

    Srcum Meeting 一.Alpha阶段 第一次Scrum Meeting 第二次Scrum Meeting 第三次Scrum Meeting 第四次Scrum Meeting 第五次Scrum ...

  8. 使用registry搭建docker私服仓库

    使用registry搭建docker私服仓库 一.拉取 registry镜像 二.根据镜像启动一个容器 1.创建一个数据卷 2.启动容器 三.随机访问一个私服的接口,看是否可以返回数据 四.推送一个镜 ...

  9. spring cloud zuul的回退

    当我们使用 @EnableZuulProxy 注解来开启zuul的路由时,默认在@EnableZuulProxy注解上就包含了@EnableCircuitBreaker注解,即开启了断路器功能.那么在 ...

  10. 一张图彻底搞懂Spring循环依赖

    1 什么是循环依赖? 如下图所示: BeanA类依赖了BeanB类,同时BeanB类又依赖了BeanA类.这种依赖关系形成了一个闭环,我们把这种依赖关系就称之为循环依赖.同理,再如下图的情况: 上图中 ...