【模板】ST表


(那一天我唯一徹底搞懂的東西然而現在也忘光光)

先看題:(RP++)

先跳過暴力,這一題肯定不行的

這時就需要ST表,ST表:Sparse Table Algorithm

 ST表分為兩部分, 預處理查詢
預處理:
    采用DP的思想, f[i][ j] 表示 [i , i+2^ j  - 1] 區間中的最小值(也就是從第i個數起連續2j個數中的最小值)。
       數列3,2,4,5,6,8,1,2,9,7。f[1][0]=3,f[1][1]=2,f[1][2]=2,f[1][3]=1,f[2][0]=2,f[2][1]=2,f[2][2]=2……
       f[i][ j]可以由f[i][j-1]和f[i+2^j-1][ j-1]導出:
       f[i][ j-1]表示 區間[i , i+2^j-1-1]的最小值
       f[i+2^ j-1 ][ j-1]表示 區間[i+2^j-1 , i+2^j-1+2^j-1-1]=[i+2^j-1, i+2^j-1] 的最小值 ,所以有DP方程: f[i][ j]=min(f[i][ j-1],f[i+2^ j-1 ][ j-1])
 
這一部分都很好懂,接下來就是怎么查詢了。
 

 關於長度2k解釋:因為要完全覆蓋整個區間,而對於求最大值和最小值兩個區間有交集是沒有影響的(不是精確覆蓋),所以可以求2k<=r-l+1

例題:(裸的ST表)

代碼:

#include<iostream>
#include<cstdio>
#include<cmath> 
using namespace std;
int a[1000001];
int Fmax[100005][25];
int Fmin[100005][25];
int n,m;
void MM()
{
    for(int j=1;j<=floor(log(n)/log(2));j++)
        for(int i=1;i+(1<<j)-1<=n;i++)
        {
            Fmax[i][j]=max(Fmax[i][j-1],Fmax[i+(1<<(j-1))][j-1]);
            Fmin[i][j]=min(Fmin[i][j-1],Fmin[i+(1<<(j-1))][j-1]);
}
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
    {
    scanf("%d",&a[i]);
    Fmax[i][0]=a[i];
    Fmin[i][0]=a[i];
    }
    MM();
    int x,y;
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d",&x,&y);
        int k=floor(log(y-x+1)/log(2));
        printf("%d\n",max(Fmax[x][k],Fmax[y-(1<<k)+1][k]));
    }
    return 0;
}

提供雙倍經驗(練手)

題目指路

題解指路(wsq大佬tql%%%)

再看一道題?

(神奇矩陣)

大概思路:

 

(代碼有時間再放吧。。要月考了。。。)


免責聲明!

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



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