st表可以解決rmq問題,即區間最大值、最小值
速度快:預處理的時間複雜度是o(nlogn)。查詢的時間複雜度是o(1)。
不支援修改操作
st表借助於乙個陣列實現:st[i][j]表示從i為起點,2j個長度的區間最大值。
顯然,st[i][0]=a[i]; 即從i開始1個單位長度的最大值就是i。
然後是乙個雙層迴圈,第一層是列舉陣列的第二維下標,j從1開始(0已經預處理了),一直到log2(n),為什麼呢?因為第二維表示的是2j個長度單位,所以2log2(n)
<=n。
這裡可能對log2不理解,假設log2(n)返回的是k,那麼k是2k
<=n的最大整數。例如log2(4)=2 log2(5)=2 log2(6)=2 log2(7)=2 log2(8)=3 ……
所以說,j列舉到log2(n)就行了。
第二層迴圈列舉的是i,是第一維下標,從一開始,一直到i+(1我們推出狀態轉移方程:st[i][j]=max(st[i][j-1],st[i+(1<<(j-1))][j-1]); //dp的思想,兩段的最大值就是整個區間的最大值。依舊不明白可以自己手推一遍試試。
為什麼要先迴圈j呢?因為我們初始化的是st[i][0],如果先迴圈i就會有一些分段還未求出。(建議大家手推一遍試試)
這樣,預處理就結束了。
每一次讀入要查詢的區間l--r,令k=log2(r-l+1).為什麼呢?r-l+1其實就是區間的長度。
令len=r-l+1,很顯然,len / 2 < 2log2(len)
<= len。所以說每一次輸出max(st[l][k],st[r-(1《在這裡st[i][k]一定越過了l--r區間的中點,st[r-(1附上**:
1 #include2 #include3 #include//注意一定要用scanf和printf,否則會超時
4using
namespace
std;
5int n,m,a[200005],st[200005][35];6
intmain()
12for(int j=1;j<=log2(n);j++)16}
17for(int i=1;i<=m;i++)
23return0;
24 }
我建議大家感性理解一下,
要準確地證明真的比較難
。大家可以手算模擬一遍。
模板 ST表 洛谷P3865
題目背景 這是一道st表經典題 靜態區間最大值 請注意最大資料時限只有0.8s,資料強度不低,請務必保證你的每次查詢複雜度為 o 1 題目描述 給定乙個長度為 n 的數列,和 m 次詢問,求出每一次詢問的區間內數字的最大值。輸入輸出格式 輸入格式 第一行包含兩個整數 n,m 分別表示數列的長度和詢問...
模板 ST表(洛谷P3865)
給定乙個長度為 n 的數列,和 m 次詢問,求出每一次詢問的區間內數字的最大值。第一行包含兩個整數 n m 分別表示數列的長度和詢問的個數。第二行包含 個整數,記為 a i 依次表示數列的第 i 項。接下來 m 行,每行包含兩個整數 l i,r i 表示查詢的區間為 l i,r i 輸出包含 m 行...
ST表 (模板) 洛谷3865
題目背景 這是一道st表經典題 靜態區間最大值 請注意最大資料時限只有0.8s,資料強度不低,請務必保證你的每次查詢複雜度為 o 1 o 1 題目描述 給定乙個長度為 n n 的數列,和 m m 次詢問,求出每一次詢問的區間內數字的最大值。輸入輸出格式 輸入格式 第一行包含兩個整數 n,m n,m ...