ST 表学习笔记

ST 表,可以用来做区间最值问题, 我们这里用来做区间的最大值,时间复杂度可以达到O(nlogn)预处理,O(1)查询答案。

基本思路

我们首先会想到的是设

maxxi,j 为左端点为 i ,右端点为 j 的区间内的最大值,状态转移方程为maxxi,j=max(maxxi,j1,aj)

然后我们可以使用 ST 表来解决

首先我们会发现一个规律:max(x,y,z)=max(max(x,y),max(y,z))

那我们就可以采用一个倍增的思想:设 fi,j 为左端点为 i ,长度为 2j 的区间最大值,我们可以根据刚才的结论将刚刚的区间进行二分操作,就可以得到状态转移方程

fi,j=max(fi,j1,fi+2j1,j1)


注意,右端点( i+2j )不能越界,那这样的话以每一个起点开始就会拆分成 log(n) 个区间,每个区间的话也能够用 O(1) 查询。

那么如何查询?

很简单,我们设做右端点为 l,r ,长度为 len ,易得 len=rl+1

从左往右弄个2log2(len)的区间,再从右往左弄一个即可。

代码:

P3865 【模板】ST表

#include <iostream> #include <cstring> #include <algorithm> #include <cmath> using namespace std; const int N = 2e5 + 10, M = 20; int n,m; int f[N][M]; int w[N]; void init() { for(int j = 0; j < M; j ++ ) for (int i = 1; i + (1 << j) - 1 <= n; i ++ )//不能越界 if(!j) f[i][j] = w[i]; else f[i][j] = max(f[i][j - 1],f[i + (1 << j - 1)][j - 1]); } int query(int l,int r) { int len = r - l + 1; int k = log(len) / log(2); return max(f[l][k],f[r - (1 << k) + 1][k]); } int main() { scanf("%d%d", &n,&m); for (int i = 1; i <= n; i ++ ) scanf("%d", &w[i]); init(); while(m -- ) { int l, r; scanf("%d%d", &l, &r); printf("%d\n",query(l,r)); } return 0; }

习题

1.P2880 [USACO07JAN] Balanced Lineup G

求区间极差,先用 ST 表算出区间内的最小值 minn 和最大值 maxx,然后将两数相减即可

2.P1890 gcd区间

直接套模板算出来每个区间的最大公约数就行,因为 gcd 也具有同样的性质


__EOF__

本文作者ljfyyds
本文链接https://www.cnblogs.com/ljfyyds/p/16523875.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   ljfyyds  阅读(83)  评论(1编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具
点击右上角即可分享
微信分享提示