1.树状数组
2.ST表
ST表
\(RMQ\),支持查询一个静态数组的区间最大值,不支持修改操作
预处理:\(o(n*lgn)\)
查询:\(o(1)\)
预处理
\(ST\)表的基本思想是倍增,预处理类似于区间\(dp\)问题
定义\(f[i][j]\)为从下标为\(i\)的元素开始,向后扩展\(2^{j}\)的距离的区间内的最大值,即\([i,i+2^j-1]\)内的最大值
转移方程类似于区间\(dp\)问题,可以从更小的区间内得到,将该区间分为两端,得到转移方程
\[f[i][j]=max(f[i][j-1],f[i+2^{j-1}][j-1])
\]
求解这个问题也就是区间\(dp\)的问题,先枚举区间长度\(j\),再枚举\(i\)
下面是边界问题,明显遍历到\(n\)会超出界限
对于\(f[i][j]\)最远会扩展到\(i+2^j-1\)的距离,所以有
\[i+2^j-1\leq n
\]
对于\(j\)的范围
\[min(i+2^j-1)\leq n\\
i=1\\
2^j \leq n\\
j \leq log_{2}^{n}\\
\]
for(int i=2;i<=n;i++)lg[i]=lg[i>>1]+1;//打表预处理lg[n]
for(int i=1;i<=n;i++)scanf("%d",&f[i][0]);
for(int j=1;j<=lg[n];j++)
{
for(int i=1;i<=n-(1<<j)+1;i++)
{
f[i][j]=max(f[i][j-1],f[i+(1<<(j-1))][j-1]);//位运算要注意括号
}
}
区间查询
现在,给出一段区间\([l,r]\),要在\(ST\)表内找到一段可以覆盖这段距离的,最大的子区间
\[l+2^k-1 \leq r\\
2^k \leq r-l+1\\
k \leq lg[r-l+1]
\]
这里直接令\(j=k\)
求出第一个子区间为\(f[l][k]\)
对于第二个子区间,可以以\(r\)为终点,反向找到一个子区间根据对称,\(k\)显然是不变的,由于\(r-1 \leq l+2^k-1\leq r\)
这样处理是一定可以将区间覆盖的
设第二个子区间起始的下标为\(D\)
\[D+2^k-1=r\\
D=r-2^k+1
\]
因此,区间\([l,r]\)的最大值即为
\[k=lg[r-l+1]\\
max(f[l][k],f[r-(l<<k)+1][k])
\]
CODE
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int f[N][20],lg[N];
int n,m;
int main()
{
scanf("%d%d",&n,&m);
for(int i=2;i<=n;i++)lg[i]=lg[i>>1]+1;
for(int i=1;i<=n;i++)scanf("%d",&f[i][0]);
for(int j=1;j<=lg[n];j++)
{
for(int i=1;i<=n-(1<<j)+1;i++)
{
f[i][j]=max(f[i][j-1],f[i+(1<<(j-1))][j-1]);
}
}
while(m--)
{
int l,r;scanf("%d%d",&l,&r);int k=lg[r-l+1];
int ans=max(f[l][k],f[r-(1<<k)+1][k]);
printf("%d\n",ans);
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧