ST算法(RMQ区间最值问题)

ST算法能在O(NlogN)时间内对数列a预处理,以O(1)的时间复杂度在线回答“数列a中下标在l~r之间的数的最大(小)值是多少
预处理:
f[i][j]表示数列a中下标在子区间[i,i+2^j-1]里的数的最大(小)值,即i开始的2^j个数的最大(小)值
f[i][j]=max(f[i][j-1],f[i+2^j-1][j-1],即长度为2^j的子区间的最大值是左右两半长度为2^(j-1)的子区间的最大值中较大的一个

void ST_prework(){
   for(int i=1;i<=n;i++) f[i][0]=a[i];
   int t=log(n)/log(2)+1;
   for(int j=1;j<t;j++){
      for(int i=1;i<=n-(1<<j)+1;i++){
        fi][j]=max(f[i][j-1],f[i+(1<<(j-1))][j-1];//(此处为求最大值,最小值将max换为min即可)
     }
   }
}

询问区间[l,r]:
先计算k,满足2^k<r-l+1<2^(k+1),也就是使2的k次幂小于区间长度的前提下最大的k。那么“从l开始的2^k个数”和“以r结尾的2^k个数”这两段一定覆盖了整个区间[l,r],这两段的最大(小)值分别为f[l][k]和f[r-2^k+1,k],两者中较大(小)的那个就是整个区间[l,r]的最值。

int ST_query(int l,int r){
   int k=log(r-l+1)/log(2);
   return max(f[l][k],f[r-(1<<k)+1][k];//(此处为求最大值,最小值将max换为min即可)
}

原文地址:https://www.cnblogs.com/gcw0618/p/12231019.html

时间: 2024-10-14 10:40:16

ST算法(RMQ区间最值问题)的相关文章

poj--3264Balanced Lineup+ST算法求区间最大最小值

题目链接:点击进入 其实这种动态查询区间最大最小值的题目,解法是有很多的,像是线段树和树状数组都是可以做的.ST算法效率和上面两种是一样的,但是编码更为简单. ST算法是一种利用了递推思想进行计算的算法,令dp(i,j)表示从i开始长度为2^j的一段元素中的最小值,则dp(i,j)=min(dp(i,j-1),dp(i+2^(j-1),j-1)).这是求区间最小值的递归关系,其实求区间最大值也是一样的. 代码如下: #include<iostream> #include<cstring&

rmq区间最值

时间复杂度O(NlogN)+O(Q) int a[N]; int dpmax[N][20],dpmin[N][20]; void first(int n)//预处理长度为n的数组 { mm(dpmax,0); mm(dpmin,0); rep(i,1,n+1) { dpmax[i][0]=a[i]; } for(int j=1;(1<<j)<=n;j++) { for(int i=1;i+(1<<j)-1<=n;i++) { dpmax[i][j]=max(dpmax[

hdu 5289 Assignment 【ST算法】

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5289 题意:求满足最大值减最小值小于k的区间的数目. 枚举左端点,二分右端点,用st算法求区间最值 代码: #include <stdio.h> #include <ctime> #include <math.h> #include <limits.h> #include <complex> #include <string> #incl

RMQ问题之ST算法

RMQ问题之ST算法 RMQ(Range Minimum/Maximum Query)问题,即区间最值问题.给你n个数,a1 , a2 , a3 , ... ,an,求出区间 [ l , r ]的最大值. 举例:a={ 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 },求出区间[4 ,8]中的最值.(答案:8 ) 这个问题最朴素的想法是用一个循环每次比较大小,但是,当数据范围较大时,这个算法十分低效.这时我们往往使用 ST 算法解决这个问题.虽然线段树和树状数组都能解决,但

ST算法(倍增)(用于解决RMQ)

ST算法 在RMQ(区间最值问题)问题中,我了解到一个叫ST的算法,实质是二进制的倍增. ST算法能在O(nlogn)的时间预处理后,用O(1)的时间在线回答区间最值. f[i][j]表示从i位起的2^j个数中的最大(最小)数,即[i,i+2^j-1]中的最大(最小)值,从其定义中可以看出来. 下面的实现代码以最大值为例: 预处理: void preST(int len){ for(int i=1;i<=len;i++) f[i][0]=i; int m=log(len)/log(2)+1; f

51NOD1174 区间最大数 &amp;&amp; RMQ问题(ST算法)

RMQ问题(区间最值问题Range Minimum/Maximum Query) ST算法 RMQ(Range Minimum/Maximum Query),即区间最值查询,是指这样一个问题:对于长度为n的数列a,回答若干询问RMQ(A,i,j)(i, j<=n),返回数列a中下标在i,j之间的最小/大值.如果只有一次询问,那样只有一遍for就可以搞定,但是如果有许多次询问就无法在很快的时间处理出来.在这里介绍一个在线算法.所谓在线算法,是指用户每输入一个查询便马上处理一个查询.该算法一般用较长

RMQ(模板 ST 区间最值,频繁的间隔时间)

PS: 介绍:http://blog.csdn.net/liang5630/article/details/7917702 RMQ算法.是一个高速求区间最值的离线算法,预处理时间复杂度O(n*log(n)).查询O(1).所以是一个非常高速的算法,当然这个问题用线段树相同可以解决. 1.求区间的最大值和最小值! 代码例如以下: #include <cstdio> #include <cstring> #include <cmath> #include <iostr

RMQ问题——ST算法

什么是RMQ.ST:RMQ(Range Minimum/Maximum Query)问题,即求区间的最值.可以写一个线段树来实现,但是每次查询的时间复杂度为O(log n),若查询次数过多则可能超时.ST算法是一种离线算法,经过O(nlogn)的预处理后,可以在O(1)的时间复杂度内进行查询,缺点是无法对数据做出修改. 算法实现: 初始化:用dp实现初始化.a[]为原始数据数组f,[i][j]表示从i向后的2j个数字中的最值.显然f[i][0]=a[i]; 我们将f[i][j]分为两段,一段为a

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

RMQ (Range Minimum/Maximum Query)问题是指:对于长度为n的数列A,回答若干询问RMQ(A,i,j)(i,j<=n),返回数列A中下标在i,j里的最小(大)值,也就是说,RMQ问题是指求区间最值的问题. Balanced Lineup Time Limit: 5000MS   Memory Limit: 65536KB   64bit IO Format: %I64d & %I64u Submit Status Description For the daily