st 算法学习笔记
前言
在看这篇文章之前,请先自行了解以下几项东西:
-
1.倍增思想。
-
2.动态规划思想。
-
3.乘方位运算实现
如有错误,欢迎各位 dalao
批评指出。
什么是 算法?
st 算法是一种解决 RMQ
问题的算法。RMQ
及 Range Minimum/Maximum Query
,即区间最大最小值查询。
该算法采用了 动态规划和倍增 的思想,预处理
算法具体实现
接下来给大家讲解如何实现
我们假定是要求出
我们定义
则对于初始值,
接着是状态转移。显然,对于一个长度为
但是,当我们状态转移在枚举循环时,我们需要注意的是,我们要先枚举区间长度越小的在枚举区间长度越大的,所以
则此时,我们就可以先预处理出所有
核心代码:
void init()//预处理函数
{
for(int i=1;i<=n;++i)
dp[i][0]=a[i];//初始值
for(int j=1;(1<<j)<=n;++j)//第二维j,注意 2^j 要小于n
{
for(int i=1;i+(1<<j)-1<=n;++i)//枚举i时要保证从i开始,有一个长度为 2^j 的区间时,不能超出 n。
{
dp[i][j]=max(dp[i][j-1],dp[i+(1<<j-1)]][j-1]);//状态转移
}
}
}
最后就是如何查询的问题。
假设我们要查询的是
此时,我们可以定义一个数字
查询核心代码:
int rmq(int l,int r)
{
int k=log2(r-l+1);
return max(dp[l][k],dp[r-(1<<k)+1][k]);
}
可以发现,
算法的一些扩展
RMQ
问题的,但是这种算法的思想我们却可以继续延伸下去。
of course!
为了让大家更好理解,我这里先抛给大家一道例题,相信你做出来一定可以领会到
显而易见,这个题目就是求区间 GCD
,并且我们可与发现,GCD
我们是可以重复计算的。举个例子,
既然可以重复计算,那就肯定可以用
我们只需要把 RMQ
问题中的 c++
的内置函数 __gcd
)
代码:
#include<bits/stdc++.h>
using namespace std;
int n,m;
int a[500005];
int dp[500005][35];
void init()
{
for(int j=1;(1<<j)<=n;++j)
{
for(int i=1;i+(1<<j)-1<=n;++i)
{
dp[i][j]=__gcd(dp[i][j-1],dp[i+(1<<(j-1))][j-1]);//直接求 i~i+2^j-1 这个区间的gcd
}
}
}
int rmq(int l,int r)
{
int k=log2(r-l+1);
return __gcd(dp[l][k],dp[r-(1<<k)+1][k]);//我们只需要把 max 改为 __gcd 即可。
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;++i)
scanf("%d",&a[i]),dp[i][0]=a[i];
init();
while(m--)
{
int l,r;
scanf("%d%d",&l,&r);
printf("%d\n",rmq(l,r));
}
return 0;
}
除了在算法思想上的扩展,对于算法本身,我们也可以进行扩展。
例如
这个题目的话思路还是比较清晰的,至于具体代码实现请读者自己实践,如果实在做不出来就看一看题解吧。
后记
今天的算法就讲到这里,希望大家能有所收获,如有不懂的地方,也可以私信我。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】