日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

RMQ问题,加深对ST算法的理解(Sparse Table)

發布時間:2024/9/3 编程问答 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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)
寫出代碼:

for(int i = 1; i <= n; i++) // 邊界 {cin>>dp[i][0]; } for(int j = 1; 1<<j <= n; j++) {for(int i = 1; i+(1<<j)-1<=n; i++) // 起點不同的更長區間{dp[i][j] = min(dp[i][j-1],dp[i+(1<<(j-1))][j-1]);} }

對于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=ir?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=log52.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'lrrr來表示:
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)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。