rmq學習記錄
rmq即區間最值演算法,它可以在o(nlogn)時間內進行預處理,然後在o(1)時間內回答每個查詢。
具體怎麼實現呢?
解決方法:
(一)首先是預處理,用動態規劃(dp)解決。
設a[i]是要求區間最值的數列,maxsum[i][j]表示從第i個數起連續2^j個數中的最大值。
即maxsum[i][j]=max(i,i+1......i+2^j-1)
例如:a數列為3 2 4 5 6 8 1 2 9 7
maxsum[1][0]表示第1個數起,長度為2^0=1的最大值,a[1]。
同理 maxsum[1][1]=max(a[1],a[2])=max(3,2)=3.
maxsum[1][2]=max(a[1],a[2],a[3],a[4])=max(3,2,4,5)=5
以此類推...
我們易知maxsum[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為一段。當i=1,j=3時就是3,2,4,5 和 6,8,1,2這兩段。maxsum[i][j]就是這兩段各自最大值中的最大值。
於是我們得到了狀態轉移方程maxsum[i][j]=max(maxsum[i][j-1], maxsum[i+2^(j-1)][j-1])。
核心**如下:
for(int j=1;(1注意:i和j要倒一倒
(三)查詢
假如我們需要查詢的區間為(i,j),那麼我們需要找到覆蓋這個閉區間(左邊界取i,右邊界取j)的最小冪(可以重複,比如查詢5,6,7,8,9,我們可以查詢5678和6789)。
因為這個區間的長度為j - i + 1,所以我們可以取k=log2( j-i+1),則有:i到j的最大值為max。
舉例說明,要求區間[2,8]的最大值,k = log2(8 - 2 + 1)= 2,即求max(f[2, 2],f[8 - 2 ^ 2 + 1, 2]) = max(f[2, 2],f[5, 2]);
洛谷p3865
#include
using namespace std;
int maxsum[1000001][101],a[1000001];
int main()
for(int i=1;i<=n;i++)
for(int j=1;(1for(int i=1;i<=m;i++)
return 0;
}
約束rmq 1RMQ(約束RMQ)
1rmq其實是rmq的乙個特殊情況,它的特殊性體現在 序列中每兩個相鄰元素的差是1或 1。即 對於這種特殊情況,有一種方法可以將rmq的時間降至常數級別,即用 的時間解決。可以發現,如果lca用dfs rmq的方法解決,則rmq部分正好是 1rmq。所以,如果會了這種方法,將可以用 這裡簡單 因為我...
約束rmq 約束RMQ
不知道為什麼網上找不到太多相關的資料,所以寫乙個小總結,並附有能用的 拋磚引玉。約束rmq,就是rmq區間必須滿足兩項之差最大為1,採用st表的話,這時候有o n 建表,o 1 查詢的優秀複雜度 求lca,通過dfs把原樹轉化為深度序列,就等價於求區間最小值 取到的位置 由於dfs的性質,該序列兩個...
演算法討論 RMQ 學習筆記
模板及講解 運用st表實現區間詢問區間最大 最小,初始化時間複雜度o nlog n 查詢o 1 模板題 poj 3264 include include include include define ms i,j memset i,j,sizeof i using namespace std con...