ST表
ST表是什么?
ST表是基于倍增的思想,可以实现&O(1)&的查询,但是不支持修改,ST表是解决区间最大值和最小值的问题的,解决这类为题的还可以用很多方法,例如线段树,单调队列,但是时间复杂度都不如ST表更优,所以说这篇博客我讲讲怎么利用ST表来解决这类问题
在这里说一下我对ST表的理解吧:
存储:
ST表其实就是类似于区间dp的一个查询的工具
f[i][j] 表示的是从地i个开始往后的2^i-1的最大值(min/max)
就是记录的从这个点之后的最大值,dp式子就是这个含义
就比如说 f[1][3] 就是表示的从1开始的往后2^(3-1)的位置的最大值
存储的时候还用到了倍增的原理,就是说从小往大跳
查询:
ST表的查询也就是和存储差不多吧,就是说算出
[l,r]之间最大能跳跃的长度,然后利用ST表从当前这个点往后找最大值的
特性来求出两个期间的最大值,[l,r]这个区间 的最大值max(f[l][k] , f[r-(1<<k)+1][k]);
就是说从l开始往后找k个看看最大值( 因为k是log2(r-l+1) ),所以说不用担心越界的问题
然后就开始找r端点之前的(2^k) 为止,+1是因为没有取到右端点,要取到才行
然后就是找到最大值然后输出就行了
记录:
输入的时候可以直接从f[i][0]开始输入,因为ST表的地0个也就是(2^0)就是只
包含他自己的一个数,然后存储的时候也要注意是存储的 max(f[i][j-1] , f[i+(1<<(j-1))][j-1] );
这个范围,也就是说从l开始到( 2^(j-1) )这个位置,,就拿第一个赋值开讲吧,因为f[i][0]已经被赋值过了,现在要赋值的
是f[i][1],而现在的i是1,所以要保证后面的是f[2][1],所以说 (2^(j-1) )只能是1,那就只能j是i-1了 (j从1开始的情况)
code
#include<cstdio>
#include<cmath>
#include<iostream>
const int N = 2e5+5;
const int M = 5500;
const int INF = 0x3f3f3f3f;
using namespace std;
int n,m,Ans,k,l,r;
int f[N][21];
inline int read()
{
int x=0,f=1;char ch=getchar();
while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
while (ch>='0'&&ch<='9'){x=x*10+ch-48;ch=getchar();}
return x*f;
}
inline int max(int x,int y) {return x>y?x:y;}
inline int Max(int l,int r)
{
k = log2(r-l+1);
return max(f[l][k] , f[r-(1<<k)+1][k]);
}
/*
在这里说一下我对ST表的理解吧:
存储:
ST表其实就是类似于区间dp的一个查询的工具
f[i][j] 表示的是从地i个开始往后的2^i-1的最大值(min/max)
就是记录的从这个点之后的最大值,dp式子就是这个含义
就比如说 f[1][3] 就是表示的从1开始的往后2^(3-1)的位置的最大值
存储的时候还用到了倍增的原理,就是说从小往大跳
查询:
ST表的查询也就是和存储差不多吧,就是说算出
[l,r]之间最大能跳跃的长度,然后利用ST表从当前这个点往后找最大值的
特性来求出两个期间的最大值,[l,r]这个区间 的最大值max(f[l][k] , f[r-(1<<k)+1][k]);
就是说从l开始往后找k个看看最大值( 因为k是log2(r-l+1) ),所以说不用担心越界的问题
然后就开始找r端点之前的(2^k) 为止,+1是因为没有取到右端点,要取到才行
然后就是找到最大值然后输出就行了
记录:
输入的时候可以直接从f[i][0]开始输入,因为ST表的地0个也就是(2^0)就是只
包含他自己的一个数,然后存储的时候也要注意是存储的 max(f[i][j-1] , f[i+(1<<(j-1))][j-1] );
这个范围,也就是说从l开始到( 2^(j-1) )这个位置,,就拿第一个赋值开讲吧,因为f[i][0]已经被赋值过了,现在要赋值的
是f[i][1],而现在的i是1,所以要保证后面的是f[2][1],所以说 (2^(j-1) )只能是1,那就只能j是i-1了 (j从1开始的情况)
*/
signed main()
{
n=read() ; m=read();
for(int i=1;i<=n;i++)
f[i][0] = read();
k = log2(n);
for(int j=1;j<=k;j++)
for(int i=1;i<=n;i++)
f[i][j] = max(f[i][j-1] , f[i+(1<<(j-1))][j-1] );
for(int i=1;i<=m;i++)
{
l = read() ; r = read();
printf("%d\n",Max(l,r));
}
return 0;
}
如果有错误的地方,欢迎dalao指出
凡是过往,皆为序章,前途似海,来日方长
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· 实操Deepseek接入个人知识库
· CSnakes vs Python.NET:高效嵌入与灵活互通的跨语言方案对比
· 【.NET】调用本地 Deepseek 模型
· Plotly.NET 一个为 .NET 打造的强大开源交互式图表库