RMQ区间求最值
RMQ用于区间快速查找最值,适用于期间数值无更改的情况。其预处理的复杂度为O(nlogn),查询的时间复杂度为O(1),对比于线段树的预处理O(nlogn),查询O(logn)来说,在某些情况下有着其独到的优势。
RMQ原理就是在原来的数组上跑一个dp,我们以查询最大值为例,它的状态定义是这样的:
dp[ i ][ j ]:下标从i开始,长度为2^j的区间的最大值。显然dp[ i ][ 0 ]就是下标是i的那个数字本身。
下面给出其转移方程:
dp[ i ][ j ] = max( dp[ i ][ j - 1 ], dp[ i + 2 ^ j ][ j - 1 ] )
对于询问区间[ i ~ j ]的最大值Max:
设k = log( j - i + 1 ) / log( 2 )
Max = max( dp[ i ][ k ], dp[ j - 2 ^ k + 1 ][ k ] )
上述过程的具体代码如下:
#include <cstdio>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <queue>
#include <ctime>
#include <cmath>
#include <set>
#define eps 1e-10
#define MAXN 500010
#define INF 2*0x3f3f3f3f
using namespace std; int num[MAXN], dp[MAXN][30], n, l, r; int pow(int a, int p) { //求a^p这里用了快速幂,实际用应该用一个数组预处理一下
if (p == 0) return 1;
int ans = pow(a, p / 2);
ans *= ans;
if (p % 2) ans *= a;
return ans;
} int main() {
//freopen("in.in", "r", stdin);
//freopen("out.out", "w", stdout);
scanf("%d", &n);
for (int i = 1; i <= n; i++)
scanf("%d", &num[i]); for (int i = 1; i <= n; i++) //对dp[i][0]进行初始化
dp[i][0] = num[i]; for (int j = 1; pow(2, j) <= n; j++) //上文说的转移方程
for (int i = 1; i + pow(2, j) - 1 <= n; i++)
dp[i][j] = max(dp[i][j - 1], dp[i + pow(2, j - 1)][j - 1]); scanf("%d %d", &l, &r); //求区间[l~r]之间的最大值 int k = log(r - l + 1) / log(2);
int ans = max(dp[l][k], dp[r - pow(2, k) + 1][k]);
printf("ans is : %d\n", ans); return 0;
}
RMQ问题在处理LCA中有着巨大的用处,其一种在线方法就是使用dfs+RMQ来求两个子节点的最近公共祖先问题,其大致做法就是按照访问的顺序把每个点的时间戳放入一个数组中,这样u和v的公共祖先就是数组中u和v之间时间戳最小的点,这里可以之间用RMQ在O(1)的时间内得到答案了。
RMQ区间求最值的更多相关文章
- RMQ(区间求最值)
1. 概述 RMQ(Range Minimum/Maximum Query),即区间最值查询,是指这样一个问题:对于长度为n的数列A.回答若干询问RMQ(A,i,j)(i,j<=n).返回数列A ...
- hdu4521-小明系列问题——小明序列(线段树区间求最值)
题意:求最长上升序列的长度(LIS),但是要求相邻的两个数距离至少为d,数据范围较大,普通dp肯定TLE.线段树搞之就可以了,或者优化后的nlogn的dp. 代码为 线段树解法. #include ...
- poj3264(线段树区间求最值)
题目连接:http://poj.org/problem?id=3264 题意:给定Q(1<=Q<=200000)个数A1,A2,```,AQ,多次求任一区间Ai-Aj中最大数和最小数的差. ...
- hdu 1754 I Hate It(树状数组区间求最值)2007省赛集训队练习赛(6)_linle专场
题意: 输入一行数字,查询第i个数到第j个数之间的最大值.可以修改其中的某个数的值. 输入: 包含多组输入数据. 每组输入首行两个整数n,m.表示共有n个数,m次操作. 接下来一行包含n个整数. 接下 ...
- hdu 1754 I Hate It(线段树区间求最值)
I Hate It Time Limit: 9000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total S ...
- [HDU] 2795 Billboard [线段树区间求最值]
Billboard Time Limit: 20000/8000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total ...
- nyoj 568——RMQ with Shifts——————【线段树单点更新、区间求最值】
RMQ with Shifts 时间限制:1000 ms | 内存限制:65535 KB 难度:3 描述 In the traditional RMQ (Range Minimum Q ...
- AcWing ST算法(区间求最值)打卡
一,介绍 ST算法是一个用倍增来求区间最值的算法,倍增是一个与二分类似的思想的一个东西,倍增简而言之也就是区间长度按1,2,4,8..... 我们先用nlog(n)的复杂度打出一个最大值表,后面我们可 ...
- HDU 2795.Billboard-完全版线段树(区间求最值的位置、区间染色、贴海报)
HDU2795.Billboard 这个题的意思就是在一块h*w的板子上贴公告,公告的规格为1*wi ,张贴的时候尽量往上,同一高度尽量靠左,求第n个公告贴的位置所在的行数,如果没有合适的位置贴则输出 ...
随机推荐
- SQO2008配置管理工具服务显示远程过程调用失败0x800706be
需要进行删除或更改程序里面,去卸载Microsoft SQL Server 2012 Express LocalDB就可以用了 如果还不可以看,看看是不是还有其它的占用了这个实例名 如: Micros ...
- shell脚本编程测试类型上
一bash的条件测试 判断某需求是否满足,需要由测试机制来实现.专用的测试表达式需要由测试命令辅助完成测试过程. 评估布尔声明,以便用在条件性执行中.若真,则返回0:若假,则返回1. 测试命令:• t ...
- Security基础(一):Linux基本防护措施、使用sudo分配管理权限、提高SSH服务安全
一.Linux基本防护措施 目标: 本案例要求练习Linux系统的基本防护措施,完成以下任务: 修改用户zhangsan的账号属性,设置为2015-12-31日失效(禁止登录) 锁定用户lisi的账户 ...
- Django的流程如何理解(餐厅点餐举例)
去饭店(商场)吃饭的步骤: 告诉前台服务员,来一小碗牛肉拉面,菜单上勾上一个牛肉拉面(url) 服务员去拉面窗口,告诉后厨,一碗牛肉拉面),后厨(view)开始准备. 后厨给打杂小弟说,给我一份儿面条 ...
- 自定义缓存管理器 或者 Spring -- cache
Spring Cache 缓存是实际工作中非常常用的一种提高性能的方法, 我们会在许多场景下来使用缓存. 本文通过一个简单的例子进行展开,通过对比我们原来的自定义缓存和 spring 的基于注释的 c ...
- MySQL导入导出数据和表结构 source和mysqldump
MySQL导入数据的方式: 1.使用source /dir/test.sql导入数据进入数据库:查询数据库编码格式show variables like "%char%";设置编码 ...
- prim算法【最小生成树1】
适用范围:要求无向图 prim算法(读者可以将其读作“普里姆算法”)用来解决最小生成树问题, 其基本思想是: ·对图G(VE)设置集合S,存放已被访问的顶点, ·然后每次从集合V-S中选择与集合S的最 ...
- 力扣算法——134GasStation【M】
在一条环路上有 N 个加油站,其中第 i 个加油站有汽油 gas[i] 升. 你有一辆油箱容量无限的的汽车,从第 i 个加油站开往第 i+1 个加油站需要消耗汽油 cost[i] 升.你从其中的一个加 ...
- 7.Jmeter 快速入门教程--录制复杂web测试脚本
Jmeter的功能简单,不需要有脚本语言的编写经验,纯图形界面添加测试场景, 用起来上手很快.但是如果手动添加每一个web(http/https)请求,费时又费力.而且有可能最后手动编写的和实际发的请 ...
- C#基本语法1 ----> 实例
| 版权声明:本文为博主原创文章,未经博主允许不得转载. ///////////////////////////////////////////////////////////////////// ...