转载于:http://blog.csdn.net/xuzengqiang/article/details/7350465

RMQ算法全称为(Range Minimum/Maximum Query)意思是给你一个长度为n的数组A,求出给定区间的最值的下标。当然我们可以采用枚举,但是我们也可以使用线段树来优化,复杂度为(nlogn),但是最好的办法是采用Sparse_Table算法,简称ST算法。他能在进行(nlogn)的预处理后达到n(1)的效率。下面来分析下最大值和最小值,都要用到DP的思想。

最小值(Mininun):我们可以用F(i,j)表示区间[i,i+2^j-1]间的最小值。我们可以开辟数组来保存F(i,j)的值,例如:F(2,4)就是保存区间[2,2+2^4-1]=[2,17]的最小值。那么F(i,0)的值是确定的,就为i这个位置所指的元素值,这时我们可以把区间[i,i+2^j-1]平均分为两个区间,因为j>=1的时候该区间的长度始终为偶数,可以分为区间[i,i+2^(j-1)-1]和区间[i+2^(j-1)-1,i+2^j-1],即取两个长度为2^(j-1)的块取代和更新长度为2^j的块,那么最小值就是这两个区间的最小值的最小值,动态规划为:F[i,j]=min(F[i,j-1],F[i+2^(j-1),j-1]).同理:最大值就是F[i,j]=max(F[i,j-1],F[i+2^(j-1),j-1]).

现在求出了F[i,j]之后又是怎样求出最大值或者最小值的,怎么转换为o(1)这种算法的~这就是ST算法:

这个时候询问时只要取k=ln(j-i+1)/ln2即可,那么可以令A为i到2^k的块,和B为到2^k结束的长度为2^k的块;那么A,B都是区间[i,j]的子区间,所以即求A区间的最小值和B区间的最小值的最小值。这个时候动态规划为:RMQ(i,j)=min(F[i,k],F[j-2^k+1,k]);

log2的求法:

Log[0] = -1;
for(int i = 1;i <M;i++)
Log[i] = ((i&(i-1)) == 0)?Log[i-1]+1:Log[i-1];

RMQ:

void RMQ(int n)
{
int i,j;
int m=Log[n];
for(i=1;i<=n;i++)
dp_min[i][0]=dp_max[i][0]=dis[i];//dis代表原数列
for(j=1;j<=m;j++)
{
for(i=1;i<=n+1-(1<<j);i++)
{
dp_max[i][j]=max(dp_max[i][j-1],dp_max[i+(1<<(j-1))][j-1]);
dp_min[i][j]=min(dp_min[i][j-1],dp_min[i+(1<<(j-1))][j-1]);
}
}
}

最小值:

int lcp(int x,int y)
{
int m=Log[y-x+1];
return min(dp_min[x][m],dp_min[y+1-(1<<m)][m]);
}

最大值

int lcp(int x,int y)
{
int m=Log[y-x+1];
return max(dp_max[x][m],dp_max[y+1-(1<<m)][m]);
}

RMQ求区间最值 nlog(n)的更多相关文章

  1. hdu3183 rmq求区间最值的下标

    两个月前做的题,以后可以看看,是rmq关于求区间最值的下标 /* hdu3183 终点 给一个整数,可以删除m位,留下的数字形成一个新的整数 rmq 取n-m个数,使形成的数最小 */ #includ ...

  2. 【模板】 RMQ求区间最值

    RMQ RMQ简单来说就是求区间的最大值(最小值) 核心算法:动态规划 RMQ(以下以求最大值为例) F[i,j]表示 从 i 开始 到i+2j -1这个区间中的最大值 状态转移方程 F[i,j]=m ...

  3. POJ - 3264 Balanced Lineup (RMQ问题求区间最值)

    RMQ (Range Minimum/Maximum Query)问题是指:对于长度为n的数列A,回答若干询问RMQ(A,i,j)(i,j<=n),返回数列A中下标在i,j里的最小(大)值,也就 ...

  4. xdoj-1324 (区间离散化-线段树求区间最值)

    思想 : 1 优化:题意是覆盖点,将区间看成 (l,r)转化为( l-1,r) 覆盖区间 2 核心:dp[i]  覆盖从1到i区间的最小花费 dp[a[i].r]=min (dp[k])+a[i]s; ...

  5. hdu 5443 (2015长春网赛G题 求区间最值)

    求区间最值,数据范围也很小,因为只会线段树,所以套了线段树模板=.= Sample Input3110011 151 2 3 4 551 21 32 43 43 531 999999 141 11 2 ...

  6. HDU-1754-I Hate It-线段树-求区间最值和单点修改

    开学新拉的题目,老题重做,思路会稍微比之前清晰,不过这也算是一点点进步了. 很多学校流行一种比较的习惯.老师们很喜欢询问,从某某到某某当中,分数最高的是多少. 这让很多学生很反感. 不管你喜不喜欢,现 ...

  7. hdu 1754 I Hate It (线段树求区间最值)

    HDU1754 I Hate It Time Limit:3000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u D ...

  8. RMQ(求区间最值问题)

    学习博客:https://blog.csdn.net/qq_31759205/article/details/75008659 RMQ(Range Minimum/Maximum Query),即区间 ...

  9. ST表 求 RMQ(区间最值)

    RMQ即Range Minimum/Maximun Query,中文意思:查询一个区间的最小值/最大值 比如有这样一个数组:A{3 2 4 5 6 8 1 2 9 7},然后问你若干问题: 数组A下标 ...

随机推荐

  1. Java - HttpURLConnection

    JDK中的URLConnection参数详解 1:> URL请求的类别: 分为二类,GET与POST请求.二者的区别在于: a:) get请求可以获取静态页面,也可以把参数放在URL字串后面,传 ...

  2. JS初学者必备的几个经典案例(二)!!!

    一.写出当前年份的前后5年的日期表 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" " ...

  3. Delphi指针的用法

    DELPHI指针的使用 大家都认为,C语言之所以强大,以及其自由性,很大部分体现在其灵活的指针运用上.因此,说指针是C语言的灵魂,一点都不为过.同时,这种说法也让很多人产生误解,似乎只有C语言的指针才 ...

  4. C++ - 扩展欧几里德算法非递归实现

    #include <iostream> using namespace std; int x, y; void get_x_y(int a, int b){ int q, r[3], s[ ...

  5. CentOS + Nginx + PHP-FPM(FastCGI) 配置CodeIgniter

    nginx官方现在已经针对centos提供了repository,所以现在可以直接通过yum来安装啦,很方便. nginx官方安装教程:http://nginx.org/en/download.htm ...

  6. C# .Net实现URL绝对路径和相对路径之间互相转换

    网站制作开发中,URL的绝对路径和相对路径之间互相转换,是经常需要用到的.以下是在C#.Net下一种实现二者互相转化的方法: [DllImport("shlwapi.dll", C ...

  7. python 中del 的用法

    python中的del用法比较特殊,新手学习往往产生误解,弄清del的用法,可以帮助深入理解python的内存方面的问题. python的del不同于C的free和C++的delete. 由于pyth ...

  8. fseek的使用

    一:概述 在官方文档里,对于fseek的描述是 Move to specified position in file,移到文件的某一个特殊位置 二:语法 status = fseek(fileID, ...

  9. JVM内存状况查看方法和分析工具-jmap

    jmap -heap 27657 Attaching to process ID 27657, please wait... Debugger attached successfully. Serve ...

  10. gulp-less插件之less文件编译成css

    gulp 是基于node的,所以第一步要确保你已经安装了node环境,具体怎么安装可以到node官网去看一下(https://nodejs.org/en/) 1.全局按钮gulp 打开node窗口输入 ...