【ST表(RMQ)】


ST表

  ST表是一種解決RMQ(區間最值問題)的強有力的工具

  它可以做到O(nlogn)預處理,O(1)查詢最值。

實現

  ST表其實是一種倍增的思想,我們就拿取最大值為例:

開一個二維數組Max,其中Max[i][j]表示從第i位開始,包括第i位在內的2^j個數中最大的數,例如Max[i][1]表示第i個數和第i+1個數中大的那個數。

 

然后就類似於二分的樣子,下一層也是拿兩個已得到的區間的最大值作比較,然后存儲。

預處理代碼

1 for(int j=1;j<=21;j++)
2     {
3         for(int i=1;i+(1<<j)-1<=n;i++)
4         {
5             Max[i][j]=max(Max[i][j-1],Max[i+(1<<(j-1))][j-1]);
6         }
7     }

  為什么要先循環j呢?因為我們是一層一層向上搜的,每一層的答案需要下面的基礎,所以把j放在外層,然后(1<<(j-1))就是把二進制的1向左移動(j-1)位,也就是2^(j-1)。

查詢  

  查詢也比較簡單,我們只需要求出k=log2(r-l+1)(求2的k次冪小於這一段區間的值,並且盡可能大),然后得到兩個區間,比較就行了

 

 (圖片來源)

然后取最大值返回就可以了

1 int ST(int l,int r)
2 {
3     int k=log2(r-l+1);
4     return max(Max[l][k],Max[r-(1<<k)+1][k]);
5 }

既然了解了這么多,不如.......(放心,都是模板題)

洛谷P3865 【模板】ST表

 1 #include<bits/stdc++.h>
 2 #define N 100005
 3 using namespace std;
 4 int n,m;
 5 int Max[N][21];
 6 int ST(int l,int r)
 7 {
 8     int k=log2(r-l+1);
 9     return max(Max[l][k],Max[r-(1<<k)+1][k]);
10 }
11 int main()
12 {
13     cin>>n>>m;
14     for(int i=1;i<=n;i++)
15     {
16         scanf("%d",&Max[i][0]);
17     }
18     for(int j=1;j<=21;j++)
19     {
20         for(int i=1;i+(1<<j)-1<=n;i++)
21         {
22             Max[i][j]=max(Max[i][j-1],Max[i+(1<<(j-1))][j-1]);
23         }
24     }
25     int l,r;
26     for(int i=1;i<=m;i++)
27     {
28         scanf("%d%d",&l,&r);
29         printf("%d\n",ST(l,r));
30     }
31     return 0;
32 }

 

洛谷P2251 質量檢測

 1 // luogu-judger-enable-o2
 2 #include<bits/stdc++.h>
 3 #define N 100005
 4 using namespace std;
 5 int n,m;
 6 int Min[N][21];
 7 int ST(int l,int r)
 8 {
 9     int k=log2(r-l+1);
10     return min(Min[l][k],Min[r-(1<<k)+1][k]);
11 }
12 int main()
13 {
14     cin>>n>>m;
15     for(int i=1;i<=n;i++)
16     {
17         scanf("%d",&Min[i][0]);
18     }
19     for(int j=1;j<=21;j++)
20     {
21         for(int i=1;i+(1<<j)-1<=n;i++)
22         {
23             Min[i][j]=min(Min[i][j-1],Min[i+(1<<(j-1))][j-1]);
24         }
25     }
26     for(int i=1;i+m-1<=n;i++)
27     {
28         printf("%d\n",ST(i,i+m-1));
29     }
30     return 0;
31 }

 

洛谷P1816 忠誠

 

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int Min[100005][21];
 4 int n,m;
 5 int ST(int l,int r)
 6 {
 7     int k=log2(r-l+1);
 8     return min(Min[l][k],Min[r-(1<<k)+1][k]);
 9 }
10 int main()
11 {
12     cin>>n>>m;
13     for(int i=1;i<=n;i++)
14     {
15         scanf("%d",&Min[i][0]);
16     }
17     for(int j=1;j<=21;j++)
18     {
19         for(int i=1;i+(1<<j)-1<=n;i++)
20         {
21             Min[i][j]=min(Min[i][j-1],Min[i+(1<<(j-1))][j-1]);
22         }
23     }
24     for(int i=1;i<=m;i++)
25     {
26         int l,r;
27         scanf("%d%d",&l,&r);
28         printf("%d ",ST(l,r));
29     }
30  } 

 


免責聲明!

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



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