Sparse Table ST表


貼一發上官松柏大犇寫的博客。


ST表(Sparse Table)是能夠區間查詢最值的數據結構,它採用倍增與dp的思想進行維護。

ST表複雜度:

  • 空間複雜度O(nlogn)
  • 預處理時間複雜度O(nlogn)
  • 查詢時間複雜度O(1)

ST表優勢:

  • ST表的價值在於用較大的空間複雜度換取的O(1) 的查詢複雜度,與線段樹O(n)O(n)O(logn) 不同,ST表的查詢部分併入主要部分程序後整體複雜度不會比線段樹高。所以是對程序效率的有效優化。

ST表劣勢:

  • O(nlogn) 的較大空間複雜度。
  • 更新操作比較困難(即一般不支持更新,只能靜態查詢)。

預處理操作:

如果我們把每個k值當做一層,我們要考慮如何把f[k][i] 用上一層的數據更新覆蓋。採用倍增的思想,我們定義:

  • f[k][i] 表示區間[i,i+2k1] (持續2k 個)的最值。

顯然上一層的覆蓋範圍正好是f[k][i] 的一半,即2k1 。那麼我們就可以用兩段剛好覆蓋住的區間[i,2k11][i+2k1,(i+2k1)+2k11] 來收集結果了:

  • f[k][i]=min{f[k1][i],f[k1][i+2k1]}

查詢操作:

同理,我們需要兩個已知的固定區間,能夠覆蓋(可以重合一部分)整個查詢區間。爲了方便查找,我們規定這兩個已知區間覆蓋的區間長度均爲2^k,並且兩個區間分別有一端爲L和R。那麼隨着這個k不斷增大,一定存在一個臨界點k,剛好覆蓋(或最少重合)這個區間。

當k滿足題意時,兩個區間分別爲[L,L+2k1][R(2k1),R] ,此時只需要滿足R(2k1)L+2k1 即可,化簡之後推出公式:

  • RL+22k+1klog2(RL+2)1

小常數優化:

由於系統計算log非常慢,所以我們可以參考這篇文章2i 的處理方法,把所有數值的log2()全部打表出來。這裏的時間複雜度只需要O(n)

int f[S][M],Log2[M],a[M];

void init(int n){//ST表的預處理
    int s=0;
    for(int i=1;i<=n;i++){
        f[0][i]=a[i];
        if(i&(i-1))Log2[i]=s;//刪除最後一位二進制,如果剛好i=1<<t則變成0
        else Log2[i]=s++;
    }
    for(int k=1;(1<<k)<=n;k++)
        for(int i=1;i+(1<<k)-1<=n;i++)
            f[k][i]=min(f[k-1][i],f[k-1][(1<<k-1)+i]);
}

int query(int L,int R){//ST表的查詢
    int k=Log2[R-L+2]-1;
    return min(f[k][L],f[k][R-(1<<k)+1]);
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章