最近也算是比较系统的整理了一下ST算法。大概把算法的意思写在了下面这张图里
然后是贴模板了。
/*
* 下标从1开始的数组val[1~n]。最大询问区间1~n
* initRMQ(n) O(nlogn)
* call: getval(a,b) O(1)
*/
int val[M];
int Max[20][M]; //max[i][j] 从j开始的,连续2^i个数字的最大值
//int Min[20][M];//min[i][j] 从j开始的,连续2^i个数字的最小值
int idx[M];//等价于 (int)log(1.0*m)/log(2.0) 若空间不足可以这样写
#define lst(L1,L2) ((L1)-(L2)+1) //求与区间长度为L1共同的右端点的长度为L2的区间的左端点。
void initRMQ(int n) {
idx[0]=-1;
for(int i=1;i<=n;i++) {
idx[i]=(i&(i-1))?idx[i-1]:idx[i-1]+1;
//Min[0][i] = val[i];
Max[0][i] = val[i];
}
for(int i=1;i<=idx[n];i++){
int m=lst(n,1<<i);
for(int j=1;j<=m;j++){
//Min[i][j]=min(Min[i-1][j],Min[i-1][j+(1<<i>>1)]);
Max[i][j]=max(Max[i-1][j],Max[i-1][j+(1<<i>>1)]);
}
}
}
int getval(int a,int b) {
int t=idx[b-a+1];
int s1=a;
int s2=lst(b,1<<t);
return max(Max[t][s1],Max[t][s2]);
//return min(Min[t][s1],Min[t][s2]);
}