RMQ:question

有一个长度为

N

N

N的数组,数组中的数是无序的(

1

<

=

n

<

=

5

1

0

5

1<=n<=5*10^5

1<=n<=5∗105)。
给定

Q

Q

Q次查询,每次给出一个区间

[

L

,

R

]

[L,R]

[L,R],问区间最值是多少。

Q

Q

Q为

3

×

1

0

6

3×10^6

3×106

浅浅地分析下?

我们拿到题的第一感觉?

  • 肯定是暴力枚举
  • 不做任何处理,直接查询(这谁都会吧)
  • O

    (

    Q

    n

    2

    )

    O(Q*n^2)

    O(Q∗n2),时间难以承受

思考下,暴力储存?

  • 因为这是区间问题,考虑区间dp
  • F

    [

    i

    ]

    [

    j

    ]

    表示区间

    [

    i

    ,

    j

    ]

    内的最值

    F[i][j]表示区间[i,j]内的最值

    F[i][j]表示区间[i,j]内的最值

  • 处理:

    O

    (

    n

    3

    )

    O(n^3)

    O(n3),查询:

    O

    (

    1

    )

    O(1)

    O(1),比上个好了点,但是还是无法承受。

进一步思考?

  • 我们上一个方案的状态转移方程是什么?
  • F

    [

    i

    ]

    [

    j

    ]

    =

    m

    a

    x

    (

    f

    [

    i

    ]

    [

    k

    ]

    ,

    f

    [

    k

    +

    1

    ]

    [

    j

    ]

    )

    (

    i

    <

    =

    k

    <

    =

    j

    )

    不需要循环枚举

    F[i][j]=max(f[i][k],f[k+1][j])(i<=k<=j)不需要循环枚举

    F[i][j]=max(f[i][k],f[k+1][j])(i<=k<=j)不需要循环枚举

  • 所以,我们真的需要那么多空间吗?
  • 于是,我们可以将

    F

    F

    F数组的含义变为

  • F

    [

    i

    ]

    [

    k

    ]

    表示区间

    [

    i

    ,

    i

    +

    k

    1

    ]

    的最值

    F[i][k]表示区间[i,i+k-1]的最值

    F[i][k]表示区间[i,i+k−1]的最值

  • 这样依旧会爆,但是这是我们迈出成功地一大步

最终?

  • 这个时候,就有一个很厉害的东西: ST表
  • 这个是什么呢?请看
  • F

    [

    i

    ]

    [

    j

    ]

    表示区间

    [

    i

    ,

    i

    +

    2

    j

    1

    ]

    内的最值

    F[i][j]表示区间[i,i+2^j-1]内的最值

    F[i][j]表示区间[i,i+2j−1]内的最值

  • 这时候,空间就不会爆!
  • 转移方程::

    F

    [

    i

    ]

    [

    j

    ]

    =

    m

    a

    x

    (

    F

    [

    i

    ]

    [

    j

    1

    ]

    ,

    F

    [

    i

    ]

    [

    i

    +

    (

    1

    <

    <

    (

    j

    1

    )

    )

    ]

    F[i][j]=max(F[i][j-1],F[i][i+(1<<(j-1))]

    F[i][j]=max(F[i][j−1],F[i][i+(1<<(j−1))]

  • <

    <

    是左移,

    1

    <

    <

    j

    =

    2

    j

    <<是左移,1<<j=2^j

    <<是左移,1<<j=2j,其实

    <

    <

    <<

    <<的优先级比

    -

    −低,所以最里面的括号可以删掉

  • 最后是:

    F

    [

    i

    ]

    [

    i

    ]

    =

    m

    a

    x

    (

    F

    [

    i

    ]

    [

    j

    1

    ]

    ,

    F

    [

    i

    ]

    [

    i

    +

    (

    1

    <

    <

    j

    1

    )

    ]

    F[i][i]=max(F[i][j-1],F[i][i+(1<<j-1)]

    F[i][i]=max(F[i][j−1],F[i][i+(1<<j−1)]

  • 为什么?
  • 我举个例子:

    F

    [

    1

    ]

    [

    3

    ]

    F[1][3]

    F[1][3]表示的是

    区间

    [

    1

    ,

    1

    +

    2

    3

    ]

    =

    [

    1

    ,

    8

    ]

    区间[1,1+2^3]=[1,8],

    区间[1,1+23]=[1,8],他就可以从

    区间

    F

    [

    1

    ,

    4

    ]

    F

    [

    5

    ,

    8

    ]

    区间F[1,4]和F[5,8]

    区间F[1,4]和F[5,8]表示

  • 怎么查询?
  • 我们可以考虑快速幂,比如

    10

    10

    10二进制表示

    1010

    1010

    1010,所以比较大小

    2

    ,

    8

    2,8

    2,8的区间即可

终极优化

  • 如果区间大小是31
  • 那么我们得连续比较

    16

    ,

    8

    ,

    4

    ,

    2

    ,

    1

    16,8,4,2,1

    16,8,4,2,1的区间

  • 复杂度可以接受,但是我们可以继续优化时间复杂度
  • 这张图片告诉我们什么道理?
  • 比较区间是可以重叠的!!
  • 那么我们这需要求出

    l

    o

    g

    2

    n

    {log_{2}}^{n}

    log2​n即可

  • 比如

    31

    31

    31,我们可以把它拆成

    [

    1

    ,

    16

    ]

    [

    15

    ,

    31

    ]

    [1,16][15,31]

    [1,16][15,31]来比较,如果预先处理好

    l

    o

    g

    2

    n

    {log_{2}}^{n}

    log2​n我们就可以以

    O

    (

    1

    )

    O(1)

    O(1)的复杂度查询!

怎么预先处理

l

o

g

2

n

{log_{2}}^{n}

log2​n

  • 有个代码可以比

    c

    m

    a

    t

    h

    cmath

    cmath的函数快很多

C

o

d

e

:

Code:

Code:

for(int i=1;i<=n;++i)
lg[i]=lg[i-1]+((1<<lg[i-1])==i);
  • 但是这里有个

    B

    U

    G

    BUG

    BUG!如果你要求

    l

    o

    g

    2

    n

    {log_{2}}^{n}

    log2​n,你需要减一

C

o

d

e

Code

Code(我自己写的模板)

#include<bits/stdc++.h>

using namespace std;
int n,m,dp[2][2000005],lo[2000005],a[2000005];
void log_2(){//求log2 n
for(int i=1;i<=n;i++)
lo[i]+=lo[i-1]+((1<<lo[i-1])==i);
}
int main()
{
cin>>n>>m;
log_2();
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=1;(1<<i)<=n;i++)
for(int j=1;j+(1<<i)-1<=n;j++)
dp[i][j]=1e9;
for(int i=1;i<=n;i++) dp[0][i]=a[i];
//初始化rmq,区间dp
for(int i=1;(1<<i)<=n;i++)
for(int j=1;j+(1<<i)-1<=n;j++)
dp[i][j]=min(dp[i-1][j],dp[i-1][j+(1<<i-1)]);
//查询
cout<<0<<endl;//题目所需QWQ
for(int w=2;w<=n;w++){
int j=w-m,i=w-1;
if(j<=0) j=1;
int k=lo[i-j+1]-1;//注意减一
cout<<min(dp[k][j],dp[k][i-(1<<k)+1])<<endl;
}
return 0;
}

注明

我这个代码是基于P1440 求m区间内的最小值的80分代码,因为本蒟蒻太蒟了,不会滚动数组,大家可以拿这道题练练手

关于这道题:
(老师提醒)

因为这题的区间长度只有m,所以可以用滚动数组,减小空间复杂度,不MLE

(自己提醒)

不要用memset!不要用memset!用了直接全部MLE,因为

浅谈RMQ问题的更多相关文章

  1. 浅谈-RMQ

    浅谈RMQ Today,我get到了一个新算法,开心....RMQ. 今天主要说一下RMQ里的ST算法(Sparse Table). RMQ(Range Minimum/Maximum Query), ...

  2. 浅谈RMQ

    RMQ是一类求区间极值的问题 有一种 \(O\left(nlogn\right)\) 的解法,用倍增实现 倍增算法 变量的定义 \(A_i\) : 原数组 \(f_{i,j}\) : 以 \(i\) ...

  3. 浅谈 Fragment 生命周期

    版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 源码:AndroidDemo/Fragment 文中如有纰漏,欢迎大家留言指出. Fragment 是在 Android 3.0 中 ...

  4. 浅谈 LayoutInflater

    浅谈 LayoutInflater 版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 源码:AndroidDemo/View 文中如有纰漏,欢迎大家留言指出. 在 Android 的 ...

  5. 浅谈Java的throw与throws

    转载:http://blog.csdn.net/luoweifu/article/details/10721543 我进行了一些加工,不是本人原创但比原博主要更完善~ 浅谈Java异常 以前虽然知道一 ...

  6. 浅谈SQL注入风险 - 一个Login拿下Server

    前两天,带着学生们学习了简单的ASP.NET MVC,通过ADO.NET方式连接数据库,实现增删改查. 可能有一部分学生提前预习过,在我写登录SQL的时候,他们鄙视我说:“老师你这SQL有注入,随便都 ...

  7. 浅谈WebService的版本兼容性设计

    在现在大型的项目或者软件开发中,一般都会有很多种终端, PC端比如Winform.WebForm,移动端,比如各种Native客户端(iOS, Android, WP),Html5等,我们要满足以上所 ...

  8. 浅谈angular2+ionic2

    浅谈angular2+ionic2   前言: 不要用angular的语法去写angular2,有人说二者就像Java和JavaScript的区别.   1. 项目所用:angular2+ionic2 ...

  9. iOS开发之浅谈MVVM的架构设计与团队协作

    今天写这篇博客是想达到抛砖引玉的作用,想与大家交流一下思想,相互学习,博文中有不足之处还望大家批评指正.本篇博客的内容沿袭以往博客的风格,也是以干货为主,偶尔扯扯咸蛋(哈哈~不好好工作又开始发表博客啦 ...

随机推荐

  1. Codeforces Round #827 (Div. 4) A-G

    比赛链接 A 题解 知识点:模拟. 时间复杂度 \(O(1)\) 空间复杂度 \(O(1)\) 代码 #include <bits/stdc++.h> #define ll long lo ...

  2. .net core Blazor+自定义日志提供器实现实时日志查看器

    场景 我们经常远程连接服务器去查看日志,比较麻烦,如果直接访问项目的某个页面就能实时查看日志就比较奈斯了,花了1天研究了下.net core 日志的原理,结合blazor实现了基本效果. 实现原理 自 ...

  3. Oracle收集统计信息的一些思考

    一.问题 Oracle在收集统计信息时默认的采样比例是DBMS_STATS.AUTO_SAMPLE_SIZE,那么AUTO_SAMPLE_SIZE的值具体是多少? 假设采样比例为10%,那么在计算单个 ...

  4. 万万没想到,除了香农计划,Python3.11竟还有这么多性能提升!

    众所周知,Python 3.11 版本带来了较大的性能提升,但是,它具体在哪些方面上得到了优化呢?除了著名的"香农计划"外,它还包含哪些与性能相关的优化呢?本文将带你一探究竟! 作 ...

  5. 支持 equals 相等的对象(可重复对象)作为 WeakHashMap 的 Key

    原文地址 代码地址 问题 长链接场景下通常有一个类似 Map<String, Set<Long>> 的结构,用来查找一个逻辑组内的哪些用户,String 类型的 Entry.k ...

  6. Android网络请求(3) 网络请求框架OkHttp

    Android网络请求(3) 网络请求框架OkHttp 本节我们来讲解OkHtpp网络请求框架 什么是网络请求框架 在我的理解中,网络请求框架是为了方便我们更加便捷规范的进行网络请求所建的类,我们通过 ...

  7. # Android网络请求(4) 网络请求框架Volley

    Android网络请求(4) 网络请求框架Volley Volley是Google在2013年5月15日到17日在旧金山Moscone中心举办网络开发者年会中推出的Android异步网络加载框架和图片 ...

  8. MIUI12解决安装charles抓包安装证书后还是提示证书不安全

    前言 我抓包这么长时间,这个问题我还是第一次遇到,导致我反复试验,明明安装证书还是提示不安全.我用新买的手机MIUI 12系统弄了半天 解决方案 首先下载证书这部分是一个坑,小米 MIUI 12系统下 ...

  9. Fastjson漏洞+复现

    1.漏洞介绍 ​​FastJson在解析json的过程中,支持使用autoType来实例化某一个具体的类,并调用该类的set/get方法来访问属性.通过查找代码中相关的方法,即可构造出一些恶意利用链. ...

  10. 【实时数仓】Day06-数据可视化接口:接口介绍、Sugar大屏、成交金额、不同维度交易额(品牌、品类、商品spu)、分省的热力图 、新老顾客流量统计、字符云

    一.数据可视化接口介绍 1.设计思路 后把轻度聚合的结果保存到 ClickHouse 中后,提供即时的查询.统计.分析 展现形式:用于数据分析的BI工具[商业智能(Business Intellige ...