【模板】st表

今天学习了一下st表  其实好几天就一直看


用禚神仙的话来说:

ST表是一种用于处理静态RMQ问题(无修改区间最值问题)的最快数据结构,书写方便使用简单效率便捷。
其中其预处理复杂度为O(nlogn),查询复杂度为O(1)。总时间复杂度为O(nlogn)。
常数远小于树状数组、线段树等毒瘤数据结构。

 

st表不支持在线修改 不支持!!!!!

 

 

一种利用dp求解区间最值的倍增算法。

 

定义:f[i][j]表示i到i+2^j-1这段区间的最大值。这里必须是i到i+2的j次方-1  别问为什么 规定!!!

 

预处理:f[i][0]=a[i]。即i到i区间的最大值就是a[i]。

 

状态转移:将f[i][j]平均分成两段,一段为f[i][j-1],另一段为f[i+2^(j-1)][j-1]。

 

两段的长度均为2^j-1。f[i][j]的最大值即这两段的最大值中的最大值。

 

得到f[i][j]=max(f[i][j-1],f[i+2^(j-1)][j-1])。

 

预处理就是运用倍增+区间动规

ST表使用DP思想求解区间最值,貌似属于区间动态规划,不过区间在增加时,每次并不是增加一个长度,而是使用倍增的思想,每次增加2^i个长度。

使用F[i,j]表示以i为起点,区间长度为2^j的区间最值,此时区间为[i,i + 2^j - 1]。

比如,F[0,2]表示区间[0,3]的最值,F[2,2]表示区间[2,5]的最值。

在求解F[i,j]时,ST算法是先对长度为2^j的区间[i,i + 2^j - 1]分成两等份,每份长度均为2^(j - 1)。之后在分别求解这两个区间的最值F[i,j - 1]和F[i + 2^(j - 1),j - 1]。,最后在结合这两个区间的最值,求出整个区间的最值。

状态转移方程是 F[i,j] = min(F[i,j - 1],F[i + 2^(j - 1),j - 1])

初始状态为:F[i,0] = A[i]。

 

例题:luogu P3685 【模板】ST表

 

主要变量

1.f[i][j] : 记录给定序列中区间[i,i+pow(2,j)-1]中的最大值。

起始条件:f[i][0]=a[i];

(根据上面的定义,f[i][0]代表[i,i]区间最小值(即a[i]:显然区间[i,i]里只有它一个数))。

2.bit[i] : bit[i]=pow(2,i)(记录2的i次方)。

起始条件:bit[0]=1,之后for循环生成即可。

3.a[i]:存给定序列。

4.LC:在生成st表时作为f[i][j]中j的循环上界。

①.在f[i][j]中,i为区间左端点,j决定了f[i][j]包括的比较过的的元素个数为2^j,区间右端点下标为i+pow(2,j)-1(注意这里有个-1);

 

②.由于我们循环生成st表时按区间长度由小到大,故先循环j(1~(int)log2(n))------ (此处的j是f[i][j]中的j)。

 

 

f[i][j]:从i出发算上i连续pow(2,j)个数的最大值

<=>从i出发连续pow(2,j-1) 与 从i+pow(2,j-1)出发连续pow(2,j-1)这两个最大值的最大值(分成两半)

方程:

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

 

 

完整代码:

#include<cstdio> 
#include<cmath>
#include<algorithm>
using namespace std;
int f[100001][40],a,x,LC,n,m,p,len,l,r;
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
    {   
        cin>>a;
        f[i][0]=a;
    }
    lc=(int)(log(n)/log(2));//自动向下取整(显然向上取整搞st表时比较最大值时容易把给定序列外头的元素也包括在内,不过这对于最大值么什么大碍,
//如果是查找最小值。。。你就杯具了)
for(int j=1;j<=lc;j++) for (int i=1;i<=n-(1<<j)+1;i++))//由于2^j为区间长度,故循环j其实就是把区间长度从1枚举到n(有可能<) f[i][j]=max(f[i][j-1],f[i+(1<<(j-1))][j-1]);//对于每一个区间长度枚举所有可行的左端点 for(int i=1;i<=m;i++) { cin>>l>>r; p=(int)(log(r-l+1)/log(2)); cout<<max(f[l][p],f[r-(1<<p)+1][p]); } return 0; }

简单的模拟一下:

 

给定一个数列2 4 3 5 1:

此时LC=2,n=5;

f[1][0]=2 f[2][0]=4 f[3][0]=3 f[4][0]=5 f[5][0]=1

当j=1时, i = 1 to 4

f[1][1]=max(f[1][0],f[2][0])=4;[1,2]

f[2][1]=4

f[3][1]=5

f[4][1]=5

当j=2时, i = 1 to n-bit[j]+1=2

f[1][2]=max(f[1][1],f[3][1])=5;

f[2][2]=5

 

posted @ 2018-09-22 18:30  _Yrh  阅读(182)  评论(0编辑  收藏  举报