ST算法:

   ID数组下标: 1   2   3   4   5   6   7   8   9
      ID数组元素: 5   7   3   1   4   8   2   9   8

1ST算法作用:

  主要应用于求区间最值上,可以把所需要求的区间极大的压缩,并且查询的复杂度为O(1)。比如我们要求一段区间上的最大值,就算是用DP的思想去做,用DP[i][j]表示从i到j区间的最大值,如果需要保存数据元素N比较多的时候,比如N=10000的时候,你开个二维数组肯定超内存,如果你用线段树做的,或许能行得通,不过如果N在更大的时候N=100000,估计线段树每次查询的复杂度为O(log n),询问比较多的时候也容易卡掉。这时候ST算法就派上用场啦~

2、ST算法的主要保存形式是F[i][k]:

  表示的是从n点为起点,长度为2^k的区间最值等价于ID[i][i+2^k-1]的区间大小,当k越大的时候,所代表的区间也越大。需要注意的一点是,区间长度都是2^k去表示的!!!

3、F[i][k]的预处理:

  同样在区间最值求解上,用动态规划的思想去求的每一区间F[i][k]的最值。
  当k=0的时候,区间则表示的变成一个点,也就是i位置上的值。所以DP的初始值也就是F[i][0]=ID[i]。
  然后,动态规划最重要的就算状态转移方程了,以最大值为例子,也就是

F[i][j]=max(F[i][j-1],F[i+2^(j-1)][j-1]);

  说下这个状态转移方程的由来,我们每次求的是F[i][j],也就是ID[]数组所表示的区间[i,i+2^j-1]:

F[i][j]=>ID[i~i+2^j-1]: 

[i.........................................................................................................................i+2^j-1]

  把这个区间二等分,也就是[i,i+2^j-1]=[i,i+2^(j-1)-1]+[i+2^(j-1),i+2^j-1],也就是F[i][j]是由F[i][j-1]和F[i+2^(j-1)][j-1]组成的,这很容易理解,也就是说,每次从二分的子区间中取最值赋值给当前的区间。从而把所有的区间的最值就这样保存下来、

二等分=>[i,i+2^j-1]=[i,i+2^(j-1)-1]+[i+2^(j-1),i+2^j-1]=>F[i][j-1]和F[i+2^(j-1)][j-1]

[i.........................................................................................................................i+2^j-1]

||

[i............................................i+2^(j-1)-1][i+2^(j-1) .....................................i+2^j-1]

4、求解区间[a,b]的最值

  然而,我们需要求的是区间[a,b],并不是这样[i,2^k],这样的区间,求这个F[i][k]表示区间有什么用呢?当然是有用的啦。我们把区间[a,b]转换一下,不就可以了吗、
  我们可以知道区间[a,b]的区间长度为b-a+1,如果你想把区间长度转换成两个2^k,然后求解两个区间的最值,你就想错了,那是不可能的,除非你能够证明任意数N=2^k+2^k,k存在整数解,然后这很明显是错误的,比如N=11就无整数解了的。ST算法的查询只有O(1),他是通过求解区间长度最大的2^k的值,也就是找出一个k,使得2^k<=b-a+1,然后通过比较区间[a,a+2^k-1]和[b-2^k+1,b]取最值实现的,这里的a+2^k-1并不一定会等于b-2^k+1,而且一般情况下都是大于的情况、
        [a...................................................................b]
        [a....................... (a+2^k-1)]
                    [(b-2^k+1)....................b]
求解这两个区间的最值也就是求解区间[a,b]最值了的。
首先我们要先求出K,计算方法就是:
           2^k=b-a+1 
           =>k=log2(b-a+1) 

        =>k=lg(b-a+1) /lg(2)

        =>k=(int)(log(b-a+1.0)/log(2.0));

(PS:C中的lg的计算是用log表示Orz,Orz,Orz........)

5,一些证明:

  求解出的k表示的是长度b-a+1表示成2的N次方,最大能够表示的N,一定会使得:2^k<=b-a+1.

证明:2^k>=(b-a+1)/2。        

  假设求的的k是最大的次方,如果2^k小于区间长度(b-a+1)的一半,

  则说明区间(b-a+1)的长度大于2个2^k,2^k+2^k=2^(k+1),

  也就是说这段区间(b-a+1)中还存在n=k+1使得2^n > 2^k,与假设不符,

  所以,2^k>=(b-a+1)/2恒成立、

代码:(2015.8.14)

 #include <iostream>
#include <stdio.h>
#include <math.h>
#define max(a,b) (a)>(b)?(a):(b)
#define min(a,b) (a)<(b)?(a):(b)
#define MAX 100010
using namespace std;
int maxsum[MAX][];
int minsum[MAX][];
int Num[MAX];
void Cread_ST(int N) //预处理->O(nlogn)
{
for(int i=;i<=N;i++)maxsum[i][]=minsum[i][]=Num[i];
int Len=(int)(log(N)/log(2.0));
for(int j = ; j <=Len; j++){
for(int i = ;i+(<<j)-<= N; i++){
int TMD=i+(<<(j-));
maxsum[i][j]=max(maxsum[i][j-],maxsum[TMD][j-]);
minsum[i][j]=min(minsum[i][j-],minsum[TMD][j-]);
}
}
}
int RMQ(int l,int r)
{
int k,TMD,Max,Min;
k=(int)(log(r-l+1.0)/log(2.0));
TMD=r-(<<k)+;
Max=max(maxsum[l][k],maxsum[TMD][k]);
Min=min(minsum[l][k],minsum[TMD][k]);
return Max-Min;
}
int main()
{
int N,i,Q,a,b,k,Max,Min;
while( scanf("%d%d",&N,&Q)!=EOF)
{
for(i=;i<=N;i++)
scanf("%d",&Num[i]);
Cread_ST(N);
while(Q--)
{
scanf("%d %d",&a,&b);
printf("%d\n",RMQ(a,b));
}
}
return ;
}
**************************************
* 作者: Wurq
* 博客: http://www.cppblog.com/wurq/
* 日期: //
**************************************

【原创】RMQ - ST算法详解的更多相关文章

  1. ST算法详解

    ST算法详解 Coded by Jelly_Goat. All rights reserved. 这个主要是说ST表的. 首先了解一下ST表是什么. 先来一个老套的情景带入. (假设所有的题目都是1s ...

  2. KMP算法详解(转自中学生OI写的。。ORZ!)

    KMP算法详解 如果机房马上要关门了,或者你急着要和MM约会,请直接跳到第六个自然段. 我们这里说的KMP不是拿来放电影的(虽然我很喜欢这个软件),而是一种算法.KMP算法是拿来处理字符串匹配的.换句 ...

  3. FloodFill算法详解及应用

    啥是 FloodFill 算法呢,最直接的一个应用就是「颜色填充」,就是 Windows 绘画本中那个小油漆桶的标志,可以把一块被圈起来的区域全部染色. 这种算法思想还在许多其他地方有应用.比如说扫雷 ...

  4. BM算法  Boyer-Moore高质量实现代码详解与算法详解

    Boyer-Moore高质量实现代码详解与算法详解 鉴于我见到对算法本身分析非常透彻的文章以及实现的非常精巧的文章,所以就转载了,本文的贡献在于将两者结合起来,方便大家了解代码实现! 算法详解转自:h ...

  5. kmp算法详解

    转自:http://blog.csdn.net/ddupd/article/details/19899263 KMP算法详解 KMP算法简介: KMP算法是一种高效的字符串匹配算法,关于字符串匹配最简 ...

  6. 机器学习经典算法详解及Python实现--基于SMO的SVM分类器

    原文:http://blog.csdn.net/suipingsp/article/details/41645779 支持向量机基本上是最好的有监督学习算法,因其英文名为support vector  ...

  7. [转] KMP算法详解

    转载自:http://www.matrix67.com/blog/archives/115 KMP算法详解 如果机房马上要关门了,或者你急着要和MM约会,请直接跳到第六个自然段.    我们这里说的K ...

  8. 【转】AC算法详解

    原文转自:http://blog.csdn.net/joylnwang/article/details/6793192 AC算法是Alfred V.Aho(<编译原理>(龙书)的作者),和 ...

  9. EM算法详解

    EM算法详解 1 极大似然估计 假设有如图1的X所示的抽取的n个学生某门课程的成绩,又知学生的成绩符合高斯分布f(x|μ,σ2),求学生的成绩最符合哪种高斯分布,即μ和σ2最优值是什么? 图1 学生成 ...

随机推荐

  1. iOS基础 - UIWebView

    一.UIWebView简介 是iOS内置的浏览器控件,可以浏览网页.打开文档等 能够加载html/htm.pdf.docx.txt等格式的文件 系统自带的Safari浏览器就是通过UIWebView实 ...

  2. iOS制作Static Library(静态库),实现多工程的连编

    在iOS开发中,我们会发现一些偏底层或基础代码是直接可以复用的,当我们换一个项目,改变的只需要是偏上层的业务逻辑代码,所以我们可以把这部分基础代码制作为一个静态库static library,并不断扩 ...

  3. jQuery插件综合应用1

    jQuery插件综合应用(一)注册   一.介绍 注册和登录是每个稍微有点规模的网站就应该有的功能.登陆功能与注册功能类似,也比注册功能要简单些.所以本文就以注册来说明jQuery插件的应用. jQu ...

  4. 基于Redis的CustomerSessionProvider(一)

    CustomerSessionProvider需要实现SessionStateStoreProviderBase 在设计Redis Session Provider的时候,需要考虑 1.是否每个用户的 ...

  5. ”Metro UI之磁贴(二)

    也来“玩”Metro UI之磁贴(二) 继昨天的“也来“玩”Metro UI之磁贴(一)”之后,还不过瘾,今天继续“玩”吧——今天把单选的功能加进来,还有磁贴的内容,还加了发光效果(CSS3,IE9+ ...

  6. BlackBerry Phonegap项目的搭建

    前言 事实上,这称不上是搭建,因为整个项目依旧是phonegap包里的例子项目,是使用ant来构建的. 准备材料: 1. JDK(不是java系的童鞋请自觉离开) 2. Apache ant http ...

  7. js中getByClass()函数

    js中getByClass()函数进化史 对于js来说,我想每一个刚接触它的人都应该会抱怨:为什么没有一个通过class来获取元素的方法.尽管现在高版本的浏览器已经支持getElementsByCla ...

  8. breakpad是Google开源的一套跨平台工具

    windows下捕获dump之Google breakpad_client的理解   breakpad是Google开源的一套跨平台工具,用于dump的处理.很全的一套东西,我这里只简单涉及break ...

  9. CF 332A Down the Hatch! 超级水题。。不过题目太长了

    A. Down the Hatch! time limit per test 2 seconds memory limit per test 256 megabytes input standard ...

  10. 一个吊丝android个人开发者的逆袭之路

    转眼间,一年多过去了,记得我开发第一款android应用的时候,那是在前年的冬天,我本人是做java的,android的学习和开发完全是业余爱好,从前年上半年到前年下半年大约花了半年的业余时间把and ...