區間最值查詢 RMQ(ST演算法)

2021-10-08 05:27:57 字數 2220 閱讀 9286

在打各種acm比賽時,經常都會出現與區間有關的題目,有的是直接要求求解區間問題,有的是需要巢狀進其它演算法作為優化手段出現。

很常見的區間問題有區間查詢,區間最值等。有的是需要單次查詢,有的需要多次查詢。

假如給定乙個陣列,要求多次查詢給定區間的最大值,你會怎麼做?

rmq,全名即區間最大值/最小值查詢(range minimum/maximum query)。

下面就是乙個模板rmq題。

給定乙個長度為 n 的數列,和 m 次詢問,求出每一次詢問的區間內數字的最大值。

洛谷(p3865 st表)

最直接的方法是直接使用for迴圈遍歷區間輸出最大值。

單次查詢可以這樣,但面對m次查詢,就意味著你需要遍歷m個區間多次,最高複雜度可達o(n*m),暴力解題需要慎重。

既然暴力不行,那麼就使用有點技巧的方法。

區間最值可以使用線段樹,但使用線段樹最合適的地方是陣列在動態變化的地方(後面博文介紹),而對於靜態陣列的查詢,則可以使用st表解決。這裡介紹用st表解決靜態區間查詢問題,st表預處理的複雜度為o(nlogn),查詢複雜度為o(1)。

st表的主體是乙個二維陣列 st[i][j] ,表示所需查詢陣列的從i到i+2j-1間的最值。例如: st[2][3] 表示第2個數到第7個數的最大值。 st演算法的思想本質是動態規劃。這裡用s表示查詢陣列。

預處理對於陣列s,可以把其劃分為兩部分(a和b),那麼陣列s的最大值則是a的最大值或是b的最大值,取他們間最大的。

所以對於每乙個st陣列表示的區間,可以拆分成兩部分,

狀態轉移方程為:st[ i ][ j ] = max, (《為位運算, 1

劃分的區間為 ( i, i+2j ) -> ( i , i+2j-1 ) + ( i+2j-1 , i+2j-1+ 2j-1 )

當j=0時,20=1,st[i][0] = s[i]。

void
init()

查詢st表建好後就要進行查詢了,st表裡面包含的就是乙個區間最值的資訊,所以查詢時則只需要通過給定區間(l,r)對st表進行查詢即可。

那麼查詢區間 (l,r) 該如何進行操作呢。由於st[i][j]是表示區間(i,i+2j),所以需要先了解(l,r)區間的長度, l = r-l+1,化為指數用k表示,k=log l 。

這時候只需要找到對應的st表的區間, 因為 l 一般來說不會剛好為 2的某個次方,或者說 由於log l 是向下取整的, 2k一般會小於l,所以要確保取到正確的區間最值,可以在(l,r)的兩頭取, 取 (l,l+2k) 與 (r-2k+1,r) 區間的最值,這樣雖然包含了重複部分,但不會影響結果。

所以ans = max

//初始化log陣列 計算log時直接查詢

int log[n+7]

;void

getlog()

上面例題給出**:

#include

#define max_n 100007

#define max_m 25

// 2^25 > 100007

using

namespace std;

int s[max_n]

,log[max_n]

;int st[max_n]

[max_m]

;int n,m;

void

init()

void

getlog()

intquery

(int l,

int r)

//這裡是快讀

inline

intread()

while

(isdigit

(ch)

)return x*f;

}int

main()

return0;

}

rmq ST演算法(矩陣最值)

已知某矩陣中的值已經確定,需求矩陣中某個小矩陣的最值 st演算法 我們可以將每一行看作一維的rmq maxx i j k 表示 第i行 j,j 1模板 include include include using namespace std const int n 1e3 7 const int in...

RMQ 區間最值查詢演算法

rmq range minimum maximum query 對於長度為n的數列a,回答若干詢問rmq a,i,j i,j n 返回數列a中下標在i,j裡的最小 大 值。主要方法 樸素 即搜尋 複雜度為o n 線段樹能在對數時間內在陣列區間上進行更新與查詢。預處理 o n 查詢 o logn 定義...

RMQ問題(區間最值查詢)

有一類問題被稱作區間最值問題,描述的是,給定 n 個元素,需要查詢下標位於 p q 之間的最大 小值。首先確定,針對每一次查詢,肯定是不能動態求最值的,因為每次都要計算,可能造成比較多的時間耗費。有 一種比較好的解決辦法是,先得到所有結果,在查詢時直接取出結果。這樣,就需要一種資料結構,能夠覆蓋所有...