專題:區間最小/最大查詢(range minimum/maximum query)rmq問題
[描述] 已知長度為l的數列a,詢問區間[l, r]中的最值。
若詢問的次數較少,可以用線性的複雜度來查詢,但如果詢問的次數過多且l過大,那麼複雜度就會很高。所以需要更快速的查詢方法。
st演算法:預處理o(nlogn),查詢指定區間的最值o(1)。
把待求區間[l, r]分為兩段長為len的區間,左邊一段為[l, l+len-1],右邊一段為[r-len+1, r],len必須使得兩段區間覆蓋待求區間。
設所求陣列為w:
那麼,所求最小值就是兩個區間的最小值的最小值:
即min(min, min)
若都在預先處理中先求得兩個區間的最小值,則每次查詢的複雜度都是o(1)。
預處理:(dp)
設dp[i][j]表示從第i個數起連續2^j個數中的最值。
dp[i][0]=a[i]1<=i<=n
dp[i][j]=min(dp[i][j-1], dp[i+2^(j-i)][j-1])
求最值:把區間[l, r]分成兩個長度為2^n的區間。
為使區間被分解後,長度為2^n,區間部分可重疊,但不可越過[l, r]。
例如 [3, 9] = [3, 6]+[6, 9]即:dp[3, 2]和dp[6, 2]
模板: (toj_2762)
#define maxn 50005
#define lowbit(x) ((x)&(-x))
int dmax[20][maxn], dmin[20][maxn];
int a[maxn], p[maxn];
int n, m;
void init()
p[0]=p[1]=0;
for (i=2; i<=n; i++) p[i]=p[i-1]+(lowbit(i)==i);
for (i=1, k=1; k<=n; i++, k*=2)
for (j=n; j>0; j--)
if (j+(1<<(i-1))<=n)
}int query(int l, int r)
以前寫的時候每次查詢都是現求對數,直接導致查詢複雜度上公升到o(log),後來才被告知應該提前求出打個表,查詢複雜度就是o(1)了。
初九
RMQ之ST表維護區間極值
令d i j 表示從i開始,長度為2 j的一段元素中的最小值,用遞推方式計算,d i j min d i j 1 d i 2 j 1,j 1 就是將 i,i 2 j 的這段區間一分為二,然後取兩段區間的極值就可以了。2 j小於等於n,所以一般來講陣列第二維開30就夠了。至於遞推的計算順序,j總是與前...
RMQ(區間最值問題)
1 概述 lca least common ancestors 即最近公共祖先,是指這樣乙個問題 在有根樹中,找出某兩個結點u和v最近的公共祖先 另一種說法,離樹根最遠的公共祖先 rmq range minimum maximum query 即區間最值查詢,是指這樣乙個問題 對於長度為n的數列a,...
RMQ問題(區間最值查詢)
有一類問題被稱作區間最值問題,描述的是,給定 n 個元素,需要查詢下標位於 p q 之間的最大 小值。首先確定,針對每一次查詢,肯定是不能動態求最值的,因為每次都要計算,可能造成比較多的時間耗費。有 一種比較好的解決辦法是,先得到所有結果,在查詢時直接取出結果。這樣,就需要一種資料結構,能夠覆蓋所有...