ST表學習筆記

看神仙學長的博客學的:傳送門html

st表介紹:

功能:

它是解決區間最值問題的一種強有力的數據結構(我也不知道應不該該叫數據結構)ios

它能夠作到O(nlogn)預處理,O(1)查詢最值算法

原理:

把給定區間分紅長度是2的冪次的小區間。先預處理出它們中的最小值是多少,而後用一種相似二分的思想由小區間到大區間比較兩個區間的最小值。數組

倍增算法:

倍增講解數據結構


不會的數學公式就只能截圖了,咕咕咕....spa

**好像仍是不太懂邊界,我果真太菜了,咕咕咕.....,只能背了.net

實現:

變量:

1.f[i][j] : 記錄給定序列中區間[i,i+pow(2,j)-1]中的最大值。 ps:f[i][0]=a[i]
2.bit[i] : bit[i]=pow(2,i)-----記錄2的i次方 能夠用位運算<<代替,不過必定要加(),不然就咕咕咕了
3.a[i] :輸入的數組
4.LC:在生成st表時做爲f[i][j]中j的循環上界。3d

例子:

設有一長度爲5的a數組:a1,a2,a3,a4,a5
長度爲1的區間[1,1],[2,2],[3,3],[4,4],[5,5]code

長度爲2的區間[1,2],[2,3],[3,4],[4,5]htm

長度爲4的區間[1,4],[2,5]

用f[i][j]表示:f[i][j]=[i,i+pow(2,j)-1]

長度爲1的區間: f[1][0] <=>[1,1]

f[2][0] <=>[2,2]

長度爲2的區間: f[1][1] <=>[1,2]

f[2][1] <=>[2,3]

f[1][2] <=>[1,4]

f[2][2] <=>[2,5]

如何求得f[i][j]的值:

f[i][j]=max(f[i][j-1],f[i+pow(2,j-1)][j-1]);

模板:

題目:

P3865 【模板】ST表

題目描述:給定一個長度爲 N 的數列,和 M 次詢問,求出每一次詢問的區間內數字的最大值。

代碼:

第一次提交:

檢查了檢查發現i和j寫反了,咕咕咕

NM仍是TLE,lzt和我查了好長時間錯誤後,發現數組開大了,咕咕咕咕.....
真是活久見了數組大了居然能tle而不是mle

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<queue>
#include<stack>
#include<vector>
#include<map>
#include<string>
#include<cstring>
#define ll long long int
#define MAXN 100001
using namespace std;
const int maxn=999999999;
const int minn=-999999999;
inline int read() {
    char c = getchar(); int x = 0, f = 1;
    while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();}
    while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
    return x * f;
}
int f[MAXN][41],a,lc,n,m,p,len,l,r;
int main()
{
    n=read(),m=read();
    for(int i=1;i<=n;++i) a=read(),f[i][0]=a;
    lc=(int)(log(n)/log(2));
    for(int j=1;j<=lc;++j)
    {
        for(int i=1;i<=n-(1<<j)+1;i++)
        {
            f[i][j]=max(f[i][j-1],f[i+(1<<(j-1))][j-1]);
        }
    }
    for(int i=1;i<=m;++i)
    {
        l=read(),r=read();
        p=(int)(log(r-l+1)/log(2));
        cout<<max(f[l][p],f[r-(1<<p)+1][p])<<'\n';
    }
    return 0;
}
相關文章
相關標籤/搜索