RMQ算法 (ST算法)
概述:
RMQ(Range Minimum/Maximum Query),即区间最值查询,是指这样一个问题:对于长度为n的数列A,回答若干询问RMQ(A,i,j)(i,j<=n),返回数列A中下标在i,j之间的最小/大值。对于一次查询,可以暴力地O(n),但是当查询次数很多的时候,这样的暴力就无法进行了。这时我们可以通过RMQ算法来解决这个问题。
RMQ(ST):(关于学习RMQ的博客:框架即讲解比较详细 , 具体代码比较好)
ST(Sparse Table)算法是一个非常有名的在线处理RMQ问题的算法,它可以在O(nlogn)时间内进行预处理,然后在O(1)时间内回答每个查询。
首先是预处理,用动态规划(DP)解决。设A[i]是要求区间最值的数列,F[i, j]表示从第i个数起连续2^j个数中的最大值。例如数列3 2 4 5 6 8 1 2 9 7,F[1,0]表示第1个数起,长度为2^0=1的最大值,其实就是3这个数。 F[1,2]=5,F[1,3]=8,F[2,0]=2,F[2,1]=4……从这里可以看出F[i,0]其实就等于A[i]。这样,DP的状态、初值都已经有了,剩下的就是状态转移方程。我们把F[i,j]平均分成两段(因为f[i,j]一定是偶数个数字),从i到i+2^(j-1)-1为一段,i+2^(j-1)到i+2^j-1为一段(长度都为2^(j-1))。用上例说明,当i=1,j=3时就是3,2,4,5 和 6,8,1,2这两段。F[i,j]就是这两段的最大值中的最大值。于是我们得到了动态规划方程F[i, j]=max(F[i,j-1], F[i + 2^(j-1),j-1])。
然后是查询。取k=[log2(j-i+1)],则有:RMQ(A, i, j)=min{F[i,k],F[j-2^k+1,k]}。 举例说明,要求区间[2,8]的最大值,就要把它分成[2,5]和[5,8]两个区间,因为这两个区间的最大值我们可以直接由f[2,2]和f[5,2]得到。
int vec[MAX_N];
int dp[MAX_N][];
void ST(int N)
{
for(int i=;i<=N;i++) dp[i][] = vec[i];
for(int j=;(<<j) <= N;j++)
{
for(int i=;i+(<<j)-<=N;i++)
{
dp1[i][j] = max(dp[i][j-],dp[i+(<<j-)][j-]); //由于移位操作的优先度低,1<<j-1 = 1<<(j-1);
}
}
}
int RMQ(int l,int r)
{
int k = ;
while((<<k+) <= r-l+) k++;
return max(dp1[l][k],dp1[r-(<<k)+][k]);
}
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
const int MAX_N = 5e4+;
const int INF = 1e9+;
int vec[MAX_N];
int dp1[MAX_N][];
int dp2[MAX_N][];
void ST(int N)
{
for(int i=;i<=N;i++) dp1[i][] = dp2[i][] = vec[i];
for(int j=;(<<j)<=N;j++)
{
for(int i=;i+(<<j)- <= N;i++)
{
dp1[i][j] = max(dp1[i][j-],dp1[i+(<<j-)][j-]);
dp2[i][j] = min(dp2[i][j-],dp2[i+(<<j-)][j-]);
}
}
}
int RMQ(int l,int r)
{
int k = ;
while((<<k+) <= r-l+) k++;
return max(dp1[l][k],dp1[r-(<<k)+][k]) - min(dp2[l][k],dp2[r-(<<k)+][k]);
}
int main()
{
int N,M,T;
while(cin>>N>>M)
{
for(int i=;i<=N;i++)
{
scanf("%d",&vec[i]);
}
ST(N);
for(int i=;i<M;i++)
{
int l,r;
scanf("%d%d",&l,&r);
int ans = RMQ(l,r);
printf("%d\n",ans);
}
}
return ;
}
RMQ算法 (ST算法)的更多相关文章
- RMQ的ST算法
·RMQ的ST算法 状态设计: F[i, j]表示从第i个数起连续2^j个数中的最大值 状态转移方程(二进制思想): F[i, j]=max(F[i,j-1], ...
- [总结]RMQ问题&ST算法
目录 一.ST算法 二.ST算法の具体实现 1. 初始化 2. 求出ST表 3. 询问 三.例题 例1:P3865 [模板]ST表 例2:P2880 [USACO07JAN]平衡的阵容Balanced ...
- RMQ(ST算法)
RMQ(Range Minimum/Maximum Query),即区间最值查询,是指这样一个问题:对于长度为n的数列a,回答若干询问RMQ(A,i,j)(i, j<=n),返回数列a中下标在i ...
- RMQ之ST算法模板
#include<stdio.h> #include<string.h> #include<iostream> using namespace std; ; ],M ...
- RMQ问题+ST算法
一.相关定义 RMQ问题 求给定区间的最值: 一般题目给定许多询问区间. 常见问题:对于长度为n的数列A,回答若干询问RMQ(A,i,j)(i,j<=n),返回数列A中下标在i,j之间的最小/大 ...
- RMQ问题——ST算法
比赛当中,常会出现RMQ问题,即求区间最大(小)值.我们该怎样解决呢? 主要方法有线段树.ST.树状数组.splay. 例题 题目描述 2008年9月25日21点10分,酒泉卫星发射中心指控大厅里,随 ...
- LCA在线算法ST算法
求LCA(近期公共祖先)的算法有好多,按在线和离线分为在线算法和离线算法. 离线算法有基于搜索的Tarjan算法较优,而在线算法则是基于dp的ST算法较优. 首先说一下ST算法. 这个算法是基于RMQ ...
- RMQ问题ST算法 (还需要进一步完善)
/* RMQ(Range Minimum/Maximum Query)问题: RMQ问题是求给定区间中的最值问题.当然,最简单的算法是O(n)的,但是对于查询次数很多(设置多大100万次),O(n)的 ...
- RMQ 问题 ST 算法(模板)
解决区间查询最大值最小值的问题 用 $O(N * logN)$ 的复杂度预处理 查询的时候只要 $O(1)$ 的时间 这个算法是 real 小清新了 有一个长度为 N 的数组进行 M 次查询 可 ...
- RMQ之ST算法
#include <stdio.h> #include <string.h> ; int a[N]; ]; inline int min(const int &a, c ...
随机推荐
- python的time模块常用内置函数
1.Python time time()方法 Python time time() 返回当前时间的时间戳(1970纪元后经过的浮点秒数). time()方法语法: time.time() 举例: #! ...
- Java基础day01
linux:1免费 开源的操作系统,Java主要是服务器端的开发 2与window,目录结构.安全性比后者高 3常用命令 pwd.ls.cd:vi(打开一个记事本若没有就新建一个记事本) 绝对路径:都 ...
- python常用模块详解
python常用模块详解 什么是模块? 常见的场景:一个模块就是一个包含了python定义和声明的文件,文件名就是模块名字加上.py的后缀. 但其实import加载的模块分为四个通用类别: 1 使用p ...
- MySQL数据库操作
一创建数据库 1 语法(help create database) CREATE DATABASE 数据库名 charset utf8; 2 数据库命名规则: 可以由字母.数字.下划线.@.#.$ 区 ...
- 登陆模块的进化史,带大家回顾java学习历程(一)
一直在想着写点特别点的东西,让有兴趣学编程的人确实能学到点干货,今天就来随意写写. 大家在网上查找资料看到最多的demo估计就是登陆功能的演示了,为何大家偏爱拿登陆来做demo呢?因为行业应用类程序的 ...
- echart
先介绍echart: 官网: http://echarts.baidu.com 看名字就知道是百度出品的. ECharts,一个纯 Javascript 的图表库,可以流畅的运行在 PC ...
- input表单的type属性详解,不同type不同属性之间区别
目标:详解表单input标签type属性常用的属性值 一.input标签和它的type属性 PS:input 元素可以用来生成一个供用户输入数据的简单文本框. 在默认的情况下, 什么样的数据均可以输入 ...
- JavaScript作用域,内部函数比参数优先级高
var x=0; f(); console.log(x); var f=function(){ x=1; } f(); console.log(x); function f(){ x=2; } f ...
- iOS 动画篇 (三) CADisplayLink与CoreGraphics实现动画
本文主要介绍利用CoreGraphics和CADisplayLink来实现一个注水动画.来一个效果图先: 在介绍注水动画前,先介绍利用CoreGraphics实现进度条的绘制. 一.扇形进度绘制 效果 ...
- 【Docker】安装Docker及基本使用
该文以CentOS系统为例,介绍Docker安装及基本使用.为了简化安装流程,Docker 官方提供了一套安装脚本,CentOS 系统上可以使用这套脚本安装: curl -sSL https://ge ...