ST算法主要分为预处理和询问两部分
预处理先处理log数组的值(1-n),再处理f数组
f数组运用了动态规划的思想,即区间最大值为左右两区间最大值的较大值得状态转移方程: f[i][j]=max(f[i][j-1],f[i+(1<<j-1)][j-1]) (表示a[i]到a[i+2^j-1]内的最大值)
log数组 通过log[i]=log[i>>1]+1计算(通过简单的对数计算即可证该式 )
ST算法相对于线段树而言更易实现,且在极值问题上效率更高
例1数列区间最大值 :
#include<iostream>
#include<cstdio>
using namespace std;
int log[100001],f[100001][30],a[100001];
int n,m,x,y;
int main()
{
scanf("%d%d",&n,&m);//记得用scanf和printf不然容易超时
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
}
log[0]=-1;
for(int i=1;i<=n;i++)//预处理log值
{
f[i][0]=a[i];
log[i]=log[i>>1]+1;//左移右移运算符速度快,要注意优先级
}
for(int j=1;j<=20;j++)
{
for(int i=1;i+(1<<j)-1<=n;i++)
{
f[i][j]=max(f[i][j-1],f[i+(1<<j-1)][j-1]);
}
}
for(int i=1;i<=m;i++)
{
scanf("%d%d",&x,&y);
int s=log[y-x+1];
printf("%d\n",max(f[x][s],f[y-(1<<s)+1][s]));
}
return 0;
}