提高篇(1):RMQ问题与ST表
RMQ是英文Range Minimum/Maximum Query的缩写,是询问某个区间内的最值,这里讲一种解法:ST算法
ST算法通常用在要多次(10^6级别)询问区间最值的问题中,相比于线段树,它实现更简单,效率更高,但不支持修改,且一般只能维护最值。
ST算法实际上是动规,原理如下:
预处理:
一组数a[1]..a[n],设f[i][j]表示从a[i]到a[i+2^j-1]这个范围中的最值,元素个数为2^j个。
可以分成2部分,即从a[i]至a[i+2^(j-1)-1]与a[i+2^(j-1)]至a[i+2^j-1],所以
f[i][j]也可以分成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][0]=a[i],这样即可在O(n log(n))的时间内预处理f数组。
询问:
若询问区间[l,r]的最大值,可以先求出最大的x,满足2^x<=r-l+1,那么区间[l,r]=[l,l+2^x-1]U[r-2^x+1,r],两个区间的元素个数都为2^x,
所以[l,r]中的最大值为max(f[l][x],f[r-2^x+1][x]),可以在O(1)内计算出来(对于m次询问,需要O(m)的时间复杂度)。这两个区间虽然有交集,但对最值没有影响,这就是ST算法只使用于区间最值的原因。
总结:
求区间[x,y]的最大值:
k=log2(y-x+1);
ans=max(f[x][k],f[y-2^k+1][k]);
技巧:
因为cmath库中的log2函数效率不高,所以为了提高速度,通常会使用O(N)的递推预处理出1~N这N种区间长度各自对应的k值。
具体地,设log[x]表示log2(x)向下取整,则log[x]=log[x/2]+1。这样总时间复杂度为log(n*log(n)+m+n)。
放一道例题:
平衡阵容(Balanced Lineup)
题目描述
每天,农夫 John 的N(1 <= N <= 50,000)头牛总是按同一序列排队. 有一天, John决定让一些牛们玩一场飞盘比赛. 他准备找一群在对列中为置连续的牛来进行比赛. 但是为了避免水平悬殊,牛的身高不应该相差太大. John 准备了Q (1 <= Q <= 180,000) 个可能的牛的选择和所有牛的身高 (1 <= 身高 <= 1,000,000). 他想知道每一组里面最高和最低的牛的身高差别. 注意: 在最大数据上, 输入和输出将占用大部分运行时间.
输入
输出
6
3
0
[参考程序]
#include<iostream>
#include<cstring>
#include<cstdio>
#include<climits>
#include<cmath>
#include<algorithm>
using namespace std; const int N = ;
int FMAX[N][], FMIN[N][]; void RMQ(int n)
{
for(int j = ; j != ; ++j)
{
for(int i = ; i <= n; ++i)
{
if(i + ( << j) - <= n)
{
FMAX[i][j] = max(FMAX[i][j - ], FMAX[i + ( << (j - ))][j - ]);
FMIN[i][j] = min(FMIN[i][j - ], FMIN[i + ( << (j - ))][j - ]);
}
}
}
} int main()
{
int num, query;
int a, b;
while(scanf("%d %d", &num, &query) != EOF)
{
for(int i = ; i <= num; ++i)
{
scanf("%d", &FMAX[i][]);
FMIN[i][] = FMAX[i][];
}
RMQ(num);
while(query--)
{
scanf("%d%d", &a, &b);
int k = (int)(log(b - a + 1.0) / log(2.0));
int maxsum = max(FMAX[a][k], FMAX[b - ( << k) + ][k]);
int minsum = min(FMIN[a][k], FMIN[b - ( << k) + ][k]);
printf("%d\n", maxsum - minsum);
}
}
return ;
}
参考书籍:《信息学奥赛一本通·提高篇》
提高篇(1):RMQ问题与ST表的更多相关文章
- 【算法学习笔记】RMQ问题与ST表
\(0.\) RMQ问题 P1816 人话翻译 给定一个长度为\(n\)的数列\(a\),然后有\(m\)组询问,每次询问一个区间\([l,r]\)的最小值. 其中\(m,n\leq10^5\) \( ...
- 51Nod.1766.树上最远点对(树的直径 RMQ 线段树/ST表)
题目链接 \(Description\) 给定一棵树.每次询问给定\(a\sim b,c\sim d\)两个下标区间,从这两个区间中各取一个点,使得这两个点距离最远.输出最远距离. \(n,q\leq ...
- [poj3264]rmq算法学习(ST表)
解题关键:rmq模板题,可以用st表,亦可用线段树等数据结构 log10和log2都可,这里用到了对数的换底公式 类似于区间dp,用到了倍增的思想 $F[i][j] = \min (F[i][j - ...
- 【模板】RMQ问题的ST表实现
$RMQ$问题:给定一个长度为$N$的区间,$M$个询问,每次询问$[L_i,R_i]$这段区间元素的最大值/最小值. $RMQ$的高级写法一般有两种,即为线段树和$ST$表. 本文主要讲解一下$ST ...
- RMQ问题及ST表
RMQ(Range Minimum/Maximum Query)问题指的是一类对于给定序列,要求支持查询某区间内的最大.最小值的问题.很显然,如果暴力预处理的话复杂度为 \(O(n^2)\),而此类问 ...
- RMQ算法使用ST表实现
RMQ RMQ (Range Minimum Query),指求区间最小值.普通的求区间最小值的方法是暴力. 对于一个数列: \[ A_1,~ A_2,~ A_3,~ \cdots,~ A_n \] ...
- rmq问题:ST表
存板子.O(nlogn)预处理,O(1)查询.空间O(nlogn). int d[1000006][25]; int mn[1000006]; void rmq_init() { for(int i= ...
- 洛谷 P2880 [USACO07JAN]Balanced Lineup G (ST表模板)
题意:给你一组数,询问\(q\)次,问所给区间内的最大值和最小值的差. 题解:经典RMQ问题,用st表维护两个数组分别记录最大值和最小值然后直接查询输出就好了 代码: int n,q; int a[N ...
- RMQ问题 - ST表的简单应用
2017-08-26 22:25:57 writer:pprp 题意很简单,给你一串数字,问你给定区间中最大值减去给定区间中的最小值是多少? 用ST表即可实现 一开始无脑套模板,找了最大值,找了最小值 ...
随机推荐
- Qt 学习(4)
Qt UI 文件机制 使用 Qt 设计界面程序时,若界面是静态的,可以借助 Qt Designer 进行所见即所得的界面设计.设计好界面后,在界面类中对 ui 对象进行操作非常方便. QtCreato ...
- postMessage解决跨域跨窗口消息传递
平时做web开发的时候关于消息传递,除了客户端与服务器传值还有几个经常会遇到的问题 页面和其打开的新窗口的数据传递 页面与嵌套的iframe消息传递 这些问题都有一些解决办法,但html5引入的mes ...
- 参数化拼接in查询条件,个人备份
/// <summary> /// 查询数据报表 /// </summary> /// <param name="Tr ...
- sqlmap 命令笔记
基础命令 注入 MySQL mssql access 直接爆表.然后你懂的BT5里面的话前面就要加pythonsqlmap.py -u url --dbs //爆数据库sqlmap.py -u url ...
- vue-2.4.0-添加的新东东
组件内新增实现属性继承 VUE中一个比较令人烦恼的事情是属性只能从父组件传递给子组件.这也就意味着当你想向嵌套层级比较深组件数据传递,只能由父组件传递给子组件,子组件再传递给孙子组件...像下面这样 ...
- C++ VS编译问题--LINK : fatal error LNK1123: 转换到 COFF 期间失败: 文件无效或损坏
用VS编译时,当出现错误LINK : fatal error LNK1123: 转换到 COFF 期间失败: 文件无效或损坏: 这个问题的解决方案为: 1. 找到项目\xx属性\配置属性\清单工具\输 ...
- Android内存监测工具使用
用 Heap监测应用进程使用内存情况的步骤如下:1. 启动eclipse后,切换到DDMS透视图,并确认Devices视图.Heap视图都是打开的:2. 将手机通过USB链接至电脑,链接时需要确认手机 ...
- 用Android studio进行 OpenCV 开发的第一个项目
我的天! 折腾了好久终于搭建成功了第一个项目. 项目环境: Windows 7 家庭普通版 64位 Android studio 1.5.1 OpenCV-2.4.9-android-sdk 基于 ...
- System Center Configuration Manager 2016 配置安装篇(Part1)
SCCM 2016 配置管理系列(Part 1- 4) 介绍AD01上配置了Active Directory域服务(ADDS),然后将Configuration Manager服务器(CM16)加入到 ...
- JavaScript(一) 对象基础
1.定义类或对象 1.1 混合的构造函数/原型方法 用构造函数定义对象的所有非函数属性,类似于Java的构造方法.用原型方法定义对象的函数属性(方法).这种方法是使用比较广泛的定义类或对象的方法. / ...