ST表算法詳解

ST表算法詳解(算是吧)

ST表就是一個用來解決rmq(區間最值)問題的算法。
ST表不支持在線修改。
預處理時間複雜度O(nlogn),查詢時間O(1)。
ST表算法詳解(求最小值):
用mn[i][j]表示從j到j+2^i-1的最小值(長度顯然爲2^i)。
任意一段的最小值顯然等於min(前半段最小值,後半段最小值)。
那麼mn[i][j]如何用其餘狀態來繼承呢?
j到j+2^i-1的長度爲2^i,那麼一半的長度就等於2^(i-1)。
那麼前半段的狀態表示爲mn[i-1][j]。
後半段的長度也爲2^(i-1),起始位置爲j+2^(i-1)。
那麼後半段的狀態表示爲mn[i-1][j+2^(i-1)]。
因此:
mn[i][j]=min(mn[i-1][j],mn[i-1][j+2^(i-1)]。











算法

代碼實現:markdown

bin[0]=1;
for(int i=1;i<20;i++)
    bin[i]=bin[i-1]*2;//bin[i]表示2的i次方
Log[0]=-1;
for(int i=1;i<=200000;i++)
    Log[i]=Log[i/2]+1;//Log[i]表示log(i)
for(int i=1;i<=n;i++)
    mn[0][i]=a[i];//顯然i到i+2^0-1就i一個位置,那麼最小值等於本身自己的值
for(int i=1;i<=Log[n];i++)
    for(int j=1;j<=n;j++)
        if(j+bin[i]-1<=n)
            mn[i][j]=min(mn[i-1][j],mn[i-1][j+bin[i-1]]);//狀態繼承

搞定了初始化以後,剩下的就是來查詢了。
首先明白一個定理:
2^log(a)>a/2
這個很簡單,由於log(a)表示小於等於a的2的最大幾回方。
好比說log(4)=2,log(5)=2,log(6)=2,log(7)=2,log(8)=3,log(9)=3…….
那麼咱們要查詢x到y的最小值。
設len=y-x+1,t=log(len)
根據上面的定理:2^t>len/2
從位置上來講,x+2^t越過了x到y的中間!
由於位置過了一半
因此x到y的最小值能夠表示爲min(從x日後2^t的最小值,從y往前2^t的最小值)
前面的狀態表示爲mn[t][x]
設後面(從y往前2^t的最小值)的初始位置是k,
那麼k+2^t-1=y,因此k=y-2^t+1
因此後面的狀態表示爲mn[t][y-2^t+1]
因此x到y的最小值表示爲min(mn[t][x],mn[t][y-2^t+1]),因此查詢時間複雜度是O(1)














spa

代碼實現:code

int t=Log[y-x+1];
printf("%d\n",min(mn[t][x],mn[t][y-bin[t]+1]));

ST表到這裏大概就講完了。
總結的來講求rmq問題有多種方法:線段樹,ST表(表示蒟蒻只學了這兩種)….
線段樹預處理O(nlogn),查詢O(logn),支持在線修改
ST表預處理O(nlogn),查詢O(1),但不支持在線修改
要根據題目給出的時限和問題來調整解法,但願對同窗們有所幫助吧(蒟蒻奉上)



繼承

相關文章
相關標籤/搜索