poj 3246 RMQ模板
2016-05-16 21:15
351 查看
[align=center]Balanced Lineup[/align]
For the daily milking, Farmer John's N cows (1 ≤ N ≤ 50,000) always line up in the same order. One day Farmer John decides to organize a game of Ultimate Frisbee with some of the cows. To keep things simple, he will take a contiguous range of cows from the milking lineup to play the game. However, for all the cows to have fun they should not differ too much in height. Farmer John has made a list of Q (1 ≤ Q ≤ 200,000) potential groups of cows and their heights (1 ≤height ≤ 1,000,000). For each group, he wants your help to determine the difference in height between the shortest and the tallest cow in the group. Input Line 1: Two space-separated integers, N andQ. Lines 2..N+1: Line i+1 contains a single integer that is the height of cowi Lines N+2..N+Q+1: Two integers A and B (1 ≤A ≤B ≤N), representing the range of cows fromA toB inclusive. Output Lines 1..Q: Each line contains a single integer that is a response to a reply and indicates the difference in height between the tallest and shortest cow in the range. Sample Input 6 3 1 7 3 4 2 5 1 5 4 6 2 2 Sample Output 6 3 0 题意:多组测试数据,每组第一行输入n和m,分别表示n个数和m次查询,输出每次查询区间内的最大值和最小值的差。 解题思路:这是我的第一道RMQ题,表示做之前很是迷茫,不理解其中的ST算法,不过在学习了RMQ后,才发现这是个比较简单的算法,其中最难理解的可能就是ST了吧。 这个题是一道最基础的RMQ模板题,直接套用模板就可以过,也可以使用线段树,不过时间效率可能比较低,线段树讲解详见(线段树 及线段树延迟标记精讲)。RMQ算法的最大优点就是经过 O(nlogn)的预处理,是每次查询能够达到O(1),大大提高了查询效率。 下面详细介绍一下RMQ算法: RMQ算法 对于该问题,最容易想到的解决方案是遍历,复杂度是O(n)。但当数据量非常大且查询很频繁时,该算法无法在有效的时间内查询出正解。所以又引进了一种比较高效的在线算法(ST算法)解决这个问题。所谓在线算法,是指用户每输入一个查询便马上处理一个查询。该算法一般用较长的时间做预处理,待信息充足以后便可以用较少的时间回答每个查询。ST(Sparse Table)算法是一个非常有名的在线处理RMQ问题的算法,它可以在O(nlogn)时间内进行预处理,然后在O(1)时间内回答每个查询。 ST算法实质就是一个DP 例如数列A: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 35 13 65 99 88 75 64 51 42 55 66 83 12 44 65 12 f[i,j]表示的从i开始的2^j个数里面的最值。以最大值来举例说明。 f[1,0]就是从1开始的2^0个数里的最大值,既35,所以f[1,0]=35; f[1,1]就是从1开始的2^1个数里的最大值,既35,13,所以f[1,1]=35; f[1,2]就是从1开始的2^2个数里的最大值,既35,13,65,99,所以f[1,2]=99; f[2,0]就是从2开始的2^0个数里的最大值,既13,所以f[2,0]=13; f[2,3]就是从2开始的2^3个数里的最大值,既13,65,99,88,75,64,51,42,所以f[2,0]=99; 以此类推...... 从以上例子我们可以容易的看出f[i,0]就等于A[i]。(DP的初始值) 这样,DP的状态、初值都已经有了,剩下的就是状态转移方程。 求i至其后的2^j个数中的最大值,既f[i][j]的最大值,利用二分的思想,把区间i~j分成两半分别来求两个区间的最大值;就是把j分成两个长度为2^(j-1)的区间,从 i~i+2^(j-1)-1为一段,i+2^(j-1)到 i+2^j-1为一段,长度都为2^(j-1), 比如f[5,3],包含的值有88 75 64 51 42 55 66 83。 求它的最大值,就是[88 75 64 51],[42 55 66 83]的最大值中较大的。即f[5,2]和 f[9,2]。 状态转移方程既是 f[i][j]=max(f[i][j-1],f[i+2^(j-1)][j-1]); 代码如下: //次处求出2^p<=n时的p,即从i开始往后的2^j的数 int p=int(log((double)n)/log(2.0)); for(j=1;j<=p;j++) for(i=1;i+(1<<j)-1<=n;i++) { sa[i][j]=max(sa[i][j-1],sa[i+(1<<(j-1))][j-1]); si[i][j]=min(si[i][j-1],si[i+(1<<(j-1))][j-1]); } 然后是查询,假如我们需要查询的区间为f(a,b),那么我们需要找到覆盖这个闭区间(左边界取a,右边界取b)的最小幂,p=int(log((double)(b-a+1))/log(2.0));,按照之前的状态方程需要把该区间分成等长的两部分,既max(f[a][p],f[b-2^p+1][p]),得到的最大值就是所求区间的最大值,时间复杂度为惊人的O(1)。 具体代码: |
相关文章推荐
- 模板
- [bzoj 1613]: [Usaco2007 Jan]Running贝茜的晨练计划 dp
- PHP实习记录
- UTF-8解释
- 微信公共号的PHP开发(基础篇)——玩一下
- XP_版本
- VS2012打开V2013开发的项目C#方法
- 前端---html5新增标签
- hdu 2612 BFS
- bzoj2756 [SCOI2012]奇怪的游戏
- Android的特性及其平台架构介绍
- RHEL7LVM管理和ssm存储管理器使用&磁盘配额
- HDU3791 二叉搜索树
- 关于两种头文件包含及其解决办法
- 寻找最长的等差数列
- rocket mq初识(启动停止win7 下的rocket mq server)
- 关于Myeclipse10中建立web工程添加spring配置文件出现红叉错误提示的问题
- hdoj-1266-Reverse Number
- 51nod 1225 余数之和(根号n枚举)
- Java Scoket之java.io.EOFException解决方案