ST算法


ST算法

ST算法是一種用於解決RMQ(Range Minimum/Maximum Query,即區間最值查詢)問題的離線算法,類似於線段樹和樹狀數組的,其功能特性差不多,當實現起來的話,顯然是ST算法更為簡便。

ST算法的時間復雜度:預處理的是O(nlogn),查詢的是O(1);

ST表的主體式一個二維數組dp[i][j],第一個狀態表示需要需要查詢區間的首元素,第二個狀態表示從首元素開始向后延伸的長度。

 

在查詢的時候,你輸入的區間不一定總是2的倍數,那么查詢的時候便會出現區間重復查詢,但是這並不影響最后的結果,也不會影響時間復雜度。

例如:我輸入的區間是(3,11),那么我計算出來的k = (int)(log(double(r - l + 1)) / log(2.0)),即k = 3。那么我便會在區間(3,10)和(4,11)這兩個區間中去最小值返回。其中重復的區間是(4,10)。

 

 

下面就是有一份簡單的求區間最小值代碼:

其題意是:輸入n個數,以及m次查詢,每次查詢輸入l,r,表示區間的左右邊界,求區間的最小值。

#include <iostream>
#include <cstdio>
#include <cmath>

using namespace std;

int a[1005]; 
int dp[1005][20];    //該st算法的兩種狀態:
                     //   第一個表示當前區間首元素的位置
                     //    第二個狀態從當前區間首元素開始,延伸的長度

void ST_init(int n) {
    for(int i = 0; i < n; i++) {
        dp[i][0] = a[i];    //初始化區間長度為1時的值
    }
    int nlen = (int)(log((double)(n)) / log(2.0));    //計算區間可倍增區間的最大次方
    for(int j = 1; j <= nlen; j++) {    
        for(int i = 0; i < n; i++) {
            dp[i][j] = min(dp[i][j - 1], dp[i + (1 << (j - 1))][j - 1]); //將當前區間分成兩個子區間求其最小值
        }
    }
}

int ST_query(int l, int r) {
    int k = (int)(log(double(r - l + 1)) / log(2.0));    //找到當前區間最大的倍增長度
    return min(dp[l][k], dp[r - (1 << k) + 1][k]);    
}

int main() {
    int n, m;
    cin >> n >> m;
    for(int i = 0; i < n; i++) {
        scanf("%d", &a[i]);
    }
    ST_init(n);
    while(m--) {
        int l, r;
        cin >> l >> r;
        cout << ST_query(l, r) << endl;
    }
    return 0;
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM