- ST算法
ST算法是用于解决RMQ问题(区间最值问题)的一种强有力的工具。
O(nlogn)预处理,O(1)查询最值,利用的是倍增的思想。
但…但是,使用ST算法的条件是没有修改操作,emmm - 算法流程(最大值为例)
①预处理
用f[i][j]表示,从i位置开始的2^j 个数中的最大值,例如f[i][j]表示的是a[i][i+2^j-1]这个区间的最大值。
转移的时候我们可以把当前区间拆成两个区间并分别取最大值。
f[i][j]分为f[i][j-1]和f[i+2^(j-1)][j-1]
②询问
询问左端点l,右端点r;
k=log2(r-l+1)
然后对于左端点和右端点分别进行查询,这样可以保证一定可以覆盖查询的区间。
左端点查询区间[l,l+2^k-1]
右端点查询区间[r-2^k+1,r]
讲的可能比较抽象,可以画个图好好理解一下 - 代码实现
代码就比较好理解了,需要注意的:1.加减乘除的优先级高于位运算 2.双重循环外层是j,下面附模板ST算法代码
const int maxn=1e5+5;
int n,m,x,y;
int a[maxn],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()
{
scanf("%d%d",&n,&m);
for(R i=1;i<=n;++i) scanf("%d",&a[i]);
for(R i=1;i<=n;++i)
f[i][0]=a[i];
for(R j=1;j<=21;++j)//计算f[i][j],外层j!
for(R i=1;i+(1<<j)-1<=n;++i)//边界条件
f[i][j]=max(f[i][j-1],f[i+(1<<j-1)][j-1]);//加减优先级高于位运算
while(m--)
{
scanf("%d%d",&x,&y);
printf("%d\n",query(x,y));
}
return 0;
}
- 就快是猪年啦,提前祝新年快乐,菜鸡新年也要继续加油鸭