RMQ问题,加深对ST算法的理解(Sparse Table)
Sparse Table(稀疏表):簡稱ST
簡介
ST 算法本質是動態規劃。
時間復雜度為:
預處理:O(nlogn)
查詢:O(1)
它 適宜用于 數據不再作出變化(也稱離線) 的 區間最值 查詢問題。
現在假設有一組數據,要求[l,r][l,r][l,r]內的最小值。
首先我們知道:
對于區間[l,r]:它的區間長度: len=r?l+1len = r-l+1len=r?l+1;
ST的基本思想:
它是基于動態規劃,狀態為:dp[i][j]dp[i][j]dp[i][j].
dp[i][j]dp[i][j]dp[i][j]表示從iii開始 區間長度為2j2^j2j 的一個區間(即[i,2j?1][i,2^j-1][i,2j?1]) 的最值
r?l+1=2jr - l + 1 = 2^jr?l+1=2j, l=i,l = i,l=i, ???>--->???> r=i+2j?1r = i+2^j-1r=i+2j?1
對于區間[l,r][l,r][l,r],可以將它分為兩個區間,即二分為兩個均勻的區間:
[l,r]???>[l,r′]+[l′,r][l,r] --->[l,r']+[l',r][l,r]???>[l,r′]+[l′,r],所以這兩個區間的區間長度為len/2len/2len/2,
如果用dp[i][j]dp[i][j]dp[i][j]表示[l,r][l,r][l,r]這個區間的最小值,
那么狀態轉移方程dp[i][j]=min(dp[i][j?1],dp[i+2j?1][j?1])dp[i][j] = min(dp[i][j-1],dp[i+2^{j-1}][j-1])dp[i][j]=min(dp[i][j?1],dp[i+2j?1][j?1]).
對它的理解:
區間長度減半:len/2=(2j)/2=2j?1len/2 = (2^j)/2 = 2^{j-1}len/2=(2j)/2=2j?1,所以兩個子區間的第二維為j?1j-1j?1。
dp[i+2j?1][j?1]dp[i+2^{j-1}][j-1]dp[i+2j?1][j?1]:
第二個子區間第一維,即開始位置為:i+len/2=i+2j?1i + len/2 = i + 2^{j-1}i+len/2=i+2j?1
邊界(即長度為1=201 = 2^01=20的子區間):
dp[i][0]=a[i](i=1...n)dp[i][0] = a[i] (i = 1...n)dp[i][0]=a[i](i=1...n)
寫出代碼:
對于i,一個區間[l,r][l,r][l,r],
dp[i][j],l=i,r?i+1=2j=1<<jdp[i][j],l = i,r-i +1 = 2^j = 1<<jdp[i][j],l=i,r?i+1=2j=1<<j
所以:
r=i+(1<<j)?1<=nr = i + (1<<j)-1<= nr=i+(1<<j)?1<=n
區間查詢:
[l,r][l,r][l,r]查詢最小值,
令kkk 為滿足 2k<=len=r?l+12 ^k <= len = r-l+12k<=len=r?l+1的最大整數,
k=log2(r?l+1)k = log2(r-l+1)k=log2(r?l+1)
解釋為什么取滿足2k<=len=r?l+12 ^k <= len = r-l+12k<=len=r?l+1的最大整數:
- 理論上2k==len2^k == len2k==len: dp[l][k]dp[l][k]dp[l][k]已經是ansansans
- 但是不能保證所有的只用一個區間就可以完全覆蓋查詢區間,會出現2k<len2^k < len2k<len的情況,比如[1,5],len=5[1,5],len = 5[1,5],len=5時,k=log5≈2.32=2k = log5≈2.32 = 2k=log5≈2.32=2,此時區間:dp[1][2]dp[1][2]dp[1][2]只覆蓋到了[1,4][1,4][1,4],需要再加上一個[1<=l<=4,5][1<=l<=4,5][1<=l<=4,5]的區間,所以再取:dp[5?4+1][2]=dp[2][2]???>[2,5]dp[5-4+1][2] = dp[2][2]--->[2,5]dp[5?4+1][2]=dp[2][2]???>[2,5]
因此對于區間[l,r][l,r][l,r]用 以lll開頭并且區間長度為2k2^k2k 和 以rrr結尾并且區間長度為2k2^k2k 的兩個區間覆蓋
那么
ans=min(dp[l][k],dp[r?(1<<k)+1][k])ans = min(dp[l][k],dp[r-(1<<k)+1][k])ans=min(dp[l][k],dp[r?(1<<k)+1][k])
l′l'l′用rrr來表示:
r?l′+1=1<<k???>l′=r?(1<<k)+1r - l' + 1 = 1 << k ---> l' = r - (1<<k) + 1r?l′+1=1<<k???>l′=r?(1<<k)+1
區間查詢代碼可寫成:
int rmq(int L, int R) {//int k = 0;//while(1<<(k+1) <= R-L+1) k++;int k = log2(r-l+1);return min(dp[l][k],dp[r-(1<<k)+1][k]); }題目:
https://www.luogu.org/problemnew/show/P1816
代碼:
(下方預處理了k)
#include <iostream> #define MAXM 100005 #define N 30 #define LL long long using namespace std; LL dp[MAXM][N]; LL lg[MAXM];//k = lg[r-l+1] int main() {int m,n;cin>>m>>n;lg[0] = -1; //注意!!for(int i = 1; i <= m; i++){cin>>dp[i][0];lg[i] = lg[i>>1] + 1; // log1 = log0 + 1 = -1 + 1 = 0...}for(int j = 1; 1<<j <= m; j++){for(int i = 1; i+(1<<j)-1<=m; i++){dp[i][j] = min(dp[i][j-1],dp[i+(1<<(j-1))][j-1]);}}int flag = 1;while(n--){int l,r;cin>>l>>r;int k = lg[r-l+1];if(flag) {cout<<min(dp[l][k],dp[r-(1<<k)+1][k]);flag = 0;}elsecout<<" "<<min(dp[l][k],dp[r-(1<<k)+1][k]);}cout<<endl;return 0; }總結
以上是生活随笔為你收集整理的RMQ问题,加深对ST算法的理解(Sparse Table)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: P1141 01迷宫(BFS+记忆化)
- 下一篇: 2019年湘潭大学程序设计竞赛(重现赛)