ST算法
ST算法其实就是倍增的实现好东西
时间复杂度O(NlogN)
我们的得先看问题:给定一个长度N的序列A,在线回答,l和r之间的数的最大值是多少。这是一个区间求最值的问题。
其实ST就是用来求最值的,树上或者是线性上。
这个题跟二分有点像,二分聪明,倍增比他还聪明。
ST算法就是用来求取区间内的最值
我们直接看 ST表 这个模板题
ST表运用的是倍增的思想
我们先设f[i][j]表示的是从i开始2j个数里面最大值,也就是[i,2j]区间内的最大值
那么我们求值的时候将区间分成两半分别进行求值
i~i+2j-1-1
2j-1~i+2j-1
然后我们需要进行 log枚举出来这个区间终点 查询覆盖
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
const int MAXN=1e6+10;
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][21];
int Query(int l,int r)
{
int k=log2(r-l+1);
return max(f[l][k],f[r-(1<<k)+1][k]);//把拆出来的区间分别取最值
//这里和之前的转移方程一样,都是用来枚举一个位置,获取看看这个区间哪一个最大
}
int main()
{
int N=read(),M=read();
for(int i=1;i<=N;i++) f[i][0]=read();//初始值
for(int j=1;j<=21;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++)
{
int l=read(),r=read();
printf("%d\n",Query(l,r));//查询区间
}
return 0;
}