RMQ问题之ST算法

RMQ(Range Minimum/Maximum Query)问题,即区间最值问题。
给你n个数,a1 , a2 , a3 , ... ,an,求出区间 [ l , r ]的最大值。

举例:
a={ 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 },求出区间[4 ,8]中的最值。(答案:8 )

这个问题最朴素的想法是用一个循环每次比较大小,但是,当数据范围较大时,这个算法十分低效。这时我们往往使用 ST 算法解决这个问题。虽然线段树和树状数组都能解决,但是ST算法更快。ST算法能做到O(1)时间的查询,而且代码实现更容易。

我们定义 f ( i , j ) 表示从i开始,长度为 2j 的一段区间中的最大值。

例如:在数列3,2,4,5,6,8,1,2,9,7中,f ( 1 , 0 )表示从第一个数开始长度为20的区间内的最大值,即f ( 1 , 0 ) = 3 , 同理f ( 1 , 1 )=3 , f ( 1 , 2 ) =5, f ( 1 , 3 ) =8。从这里很容易发现,f ( i , 0 ) 等于原数列第i个数的值。

可以通过预处理的递推计算f ( i , j ):

f ( i , j ) = max { f ( i , j-1 )  , f ( i+(1<<j-1) , j - 1 )  }

这个方程与动态规划的思想十分相似,这几乎是ST算法的核心,但是,这个方程是什么意思呢?我们将区间[ i , j ]分成两部分[ i , i+2j-1 -1 ] 与 [ i+2j-1 , i+2j -1] , 这两个区间的长度都为2j-1,分别求出两个区间最大值,在取较大的那个,就是原区间的最大值。这就是ST算法的动态转移方程。

举例:数列a={ 1 ,4 , 2 , 3 }求f ( 1 , 2 ) =max { f( 1 , 1 ) , f ( 3 , 1 ) }=max { 4 , 3 } = 4 ;
注:初始状态 f ( i , 0 ) = a [i] ;

预处理:

 void Init()//nlogn
{
log2[] = ;
for(int i = ; i <= n; i++) log2[i] = log2[i >> ] + ; //打log2表
for(int i = ; i <= n; i++) f[i][] = a[i]; //建立初始状态
for(int j = ; ( << j) <= n; j++)
{
for(int i = ; i + ( << j) - <= n; i++)
{
f[i][j] = max( f[i][j - ] , f[i + ( << j - )][j - ] ); //动态转移方程
}
}
}

查询:

查询区间[a , b ]中最大值,查询的方法比较简单,我们只需要找到一个最大整数 k ,使它满足2k<= b - a +1,例如[ 3 , 11 ] 可以分为 [ 3 , 9 ]
这里我们把待查询的区间分成两个小区间,这两个小区间满足两个条件:(1)这两个小区间要能覆盖整个区间(2)为了利用预处理的结果,要求小区间长度相等。注意两个小区间可能重叠(区间重叠不影响结果)
直接返回 max{ f[a][k] , f[b-(1<<k)+1][k] },于是就求出查询区间中的最大值。

代码如下:

 int Query(int a, int b)
{
int k = log2[b - a + ];
return max( f[a][k] , f[b - ( << k) + ][k] );
}

主程序:

 int main()
{
int m, u, v;
cin >> n;
for(int i = ; i <= n; i++)
{
cin >> arr[i];
}
Init();
cin >> m;
while(m --)
{
cin >> u >> v;
if(u > v) swap(u, v);
cout << Query(u, v) << endl;
}
return ;
}

综上,ST算法在只有查询的情况下,十分高效,在做了O(nlogn)的预处理后,可以做到O(1)的时间查询。

2016-09-14

(完)

RMQ问题之ST算法的更多相关文章

  1. RMQ问题与ST算法

    RMQ(Range Minimum/Maximum Query)问题是求区间最值问题. 对于长度为 n 的数组 A,进行若干次查询,对于区间 [L,R] 返回数组A中下标在 [L,R] 中的最小(大) ...

  2. 51NOD1174 区间最大数 && RMQ问题(ST算法)

    RMQ问题(区间最值问题Range Minimum/Maximum Query) ST算法 RMQ(Range Minimum/Maximum Query),即区间最值查询,是指这样一个问题:对于长度 ...

  3. HDU 3183 A Magic Lamp(RMQ问题, ST算法)

    原题目 A Magic Lamp Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) ...

  4. [CF 191C]Fools and Roads[LCA Tarjan算法][LCA 与 RMQ问题的转化][LCA ST算法]

    参考: 1. 郭华阳 - 算法合集之<RMQ与LCA问题>. 讲得很清楚! 2. http://www.cnblogs.com/lazycal/archive/2012/08/11/263 ...

  5. HDU 3183 - A Magic Lamp - [RMQ][ST算法]

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3183 Problem DescriptionKiki likes traveling. One day ...

  6. RMQ问题+ST算法

    一.相关定义 RMQ问题 求给定区间的最值: 一般题目给定许多询问区间. 常见问题:对于长度为n的数列A,回答若干询问RMQ(A,i,j)(i,j<=n),返回数列A中下标在i,j之间的最小/大 ...

  7. POJ 3264 Balanced Lineup RMQ ST算法

    题意:有n头牛,编号从1到n,每头牛的身高已知.现有q次询问,每次询问给出a,b两个数.要求给出编号在a与b之间牛身高的最大值与最小值之差. 思路:标准的RMQ问题. RMQ问题是求给定区间内的最值问 ...

  8. HDU 5443 The Water Problem (ST算法)

    题目链接:HDU 5443 Problem Description In Land waterless, water is a very limited resource. People always ...

  9. 求解区间最值 - RMQ - ST 算法介绍

    解析 ST 算法是 RMQ(Range Minimum/Maximum Query)中一个很经典的算法,它天生用来求得一个区间的最值,但却不能维护最值,也就是说,过程中不能改变区间中的某个元素的值.O ...

随机推荐

  1. JAVA基础学习之流的简述及演示案例、用缓冲区方法buffer读写文件、File类对象的使用、Serializable标记接口(6)

    1.流的简述及演示案例输入流和输出流相对于内存设备而言.将外设中的数据读取到内存中:输入将内存的数写入到外设中:输出.字符流的由来:其实就是:字节流读取文字字节数据后,不直接操作而是先查指定的编码表. ...

  2. python装饰器入门

    按别人的教程弄的. 要清楚基于类和基于函数的实现的不同之处. #!/usr/bin/env python # -*- coding: utf-8 -*- ''' class entryExit(obj ...

  3. Myeclipse的web工程和Eclipse互相转换

    eclipse的web工程转myeclipse的web工程1.原eclipse工程叫netschool 2.在myeclipse中新建一个工程叫netschool 并在新建的时修改 web root ...

  4. CXF学习(3) wsdl文件

    <!--一次webservice调用,其实并不是方法调用,而是发送SOAP消息 ,即xml片段--> <!--以上一篇中的wsdl文档为例,这里我将注释写到文档中 --> &l ...

  5. 攻城狮在路上(壹) Hibernate(十五)--- Hibernate的高级配置

    一.配置数据库连接池: 1.使用默认的数据库连接池: Hibernate提供了默认了数据库连接池,它的实现类为DriverManegerConnectionProvider,如果在Hibernate的 ...

  6. hdu 4063 福州赛区网络赛 圆 ****

    画几个图后,知道路径点集一定是起点终点加上圆与圆之间的交点,枚举每两个点之间是否能走,能走则连上线,然后求一遍最短路即可 #include<cstdio> #include<cstd ...

  7. 汇编学习(一)——win7 64位调出debug

    一.安装方法: 1.下载一个dosbox和win7 32位debug.exe,安装dosbox,打开页面 2. 将debug.exe放入磁盘根目录,这里以D盘为例.在dosbox中输入mount c ...

  8. windows主机开启openssl的方法

    转自:http://www.feichang56.com/openssl/

  9. Android 蹲坑的疑难杂症集锦一

    各位看官老爷子你们好,我就是那个挖坑不埋,还喜欢开新矿的小喵同志. 问大家一个问题,在Github上找项目的时候,看到中文简介说明你们是不是觉得这个项目很low不屑一顾? 最近朋友无意中说,在Gith ...

  10. JMeter正则表达式-学习(3)

    同时关联多个值的方法: { : ", : "results": : [ : : { : : : "total_earnings":"&quo ...