ST算法是适用于RMQ问题的一种算法,可以在O( nlog(n) )预处理之后,以O( 1 )的复杂度求解区间 [l,r] 的最值问题,也是采用了倍增思想
详细的思想过程放到了代码注释部分
//ST 求解 RMQ问题
#include<bits/stdc++.h>
using namespace std;
int arr[100];
int f[100][100];
//f[i][j] 表示以i为起始位置,长度为2^j的数列的最值
int main()
{
for(int i=0;i<80;i++)arr[i]=i+1;
for(int i=0;i<80;i++){
f[i][0]=arr[i];
//从任意位置开始,长度为0的数列都是只有自己的数列,所以 f[i][0] = arr[i];
}
int t=log(20)/log(2);
//如果不这样写的话,2的n次方可能会因为数字过大,循环超时
//这样写的原因是因为区间的长度是 2^t ,最长不会超过数组的长度
for(int j=1;j<=t;j++){
for(int i=0;i<20;i++){
f[i][j]=max(f[i][j-1],f[i+(1<<(j-1))][j-1]);
}
}
int l,r;
while(cin>>l>>r){//求解 [l,r]闭区间内的最大值
int k=1;
while((1<<k)<=r-l+1){
k++;
}
k--;
//k 是满足从l开始长度为 2^k并且使得 l+2^k-1不超过r的最大的k
//一旦超出边界,求得的最大值将不再是[l,r]内的,而是[l,最大边界]内的
cout<<max(f[l][k],f[r-(1<<k)+1][k])<<endl;
//[l,r]内的最值可以将区间[l,r]拆开
//利用上面求出的 k 稍加推论可以知道
// [l,r]内的最值 等同于 max(f[l][k],f[r-(1<<k)+1][k])
// f[l][k] 是从l开始长度为2^k的最值
// f[r-(1>>k)+1][k] 是从r开始往前推,长度为2^k的最大值
// 两个区间的交集 >= 原来的区间[l,r]
// 所以两个区间的最大值就是原区间的最大值
}
return 0;
}