鄂州市住房和城乡建设部网站,宁波网络公司网站建设项目,wordpress会员修改,网站建设款分录ST表主要用于解决RMQ问题#xff08;区间最值问题#xff09; 当然你可以用线段树等#xff0c;但今天用一种ST表#xff08;倍增算法#xff09;
ST表是倍增算法的一个典型应用 暴力做RMQ问题#xff0c;往往会超时#xff0c;ST表利用对其进行优化
给定一段序列A区间最值问题 当然你可以用线段树等但今天用一种ST表倍增算法
ST表是倍增算法的一个典型应用 暴力做RMQ问题往往会超时ST表利用对其进行优化
给定一段序列AST算法能在O(NlogN)的时间预处理后以O(1) 的复杂度查询在线回答在一段区间l,r 中最大小值是多少。
f[i][j]用于表示在序列a中 从第i位数字往后数2j个数这个区间内的最大值即区间[ i , i 2 j ]内取得的最大值。
而这段区域的最大值等于左右子区间的最大值,2j 2 * 2 j-1 2j-1 2j-1,把区间[i,i2j]分成[i , i 2j-1 ] [ i 2j-1 1,2j] (即f [ i ] [ j - 1 ] 与 f [ i 2 j-1 - 1 ] [ j -1 ]
我们可得F [ i ] [ j ] max ( F [ i ] [ j - 1 ] , F [ i 2 j-1 - 1 ] [ j - 1 ] ) 递推边界为f[i][0]a[i]
其实说白了就是相求大区间就先求出小区间求小区间就求小小区间一直这样套娃到最低层。
但是我们查询的区间不一定总是2的倍数也有可能会超出区间 所以我们询问区间[l,r]时要用一个kklog2(len)len为区间的长度k向下取整 lenr-l1 2tlen2t1 左右区间最大值分别是F [ l , k ] 与F [ r - 2k 1 , k ]
#includecstdio
#includeiostream
#includecmathusing namespace std;long f[100001][40];
int n,m;void ST()//预处理
{for(int k1;k(int)log2(n);k){for(int i1;in-(1k)1;i){f[i][k]max(f[i][k-1],f[i(1(k-1))][k-1]);}}
}
int query(int l,int r)//查询
{int klog2(r-l1);return max(f[l][k],f[r-(1k)1][k]);}
int a[100];
int main(){cinnm;int temp;for(int i1;in;i){scanf(%d,a[i]);f[i][0]a[i];}int l,r;for(int i1;im;i){scanf(%d%d,l,r);coutquery(l,r);}return 0;
}