学习笔记——ST算法

ST 算法

ST 算法是一种运用倍增来解决 RMQ 问题也就是区间最值问题的算法。
给定一个长度为 N 的序列 A,ST 算法能在 O(NlogN) 的时间预处理后,以 O(1) 的时间在线回答区间最值问题。
Fi,j 表示序列 A 中下标在子区间 [i,i+2j1] 里的数的最大值,也就是从 i 开始 2j 个数的最大值。边界是 Fi,0=Ai
在递推时我们将子区间的长度成倍增长,Fi,j=max(Fi,j1,Fi+2j1,j1),即长度为 2j 的子区间的最大值是左右两边长度为 2j1 的子区间的最大值中大的那一个。

for(int i=1;i<=n;i++){
	f[i][0]=a[i];
}
for(int j=1;(1<<j)<=n;j++){
	for(int i=1;i+(1<<j)-1<=n;i++){
		f[i][j]=max(f[i][j-1],f[i+(1<<(j-1))][j-1]);
	}
}

当询问区间 [l,r] 的最值时,先找出一个 k,满足 2krl+12k+1,那么从 l 开始的 2k 个数和以 r 结尾的 2k 个数一定覆盖了整个区间。
而这两段的最大值分别为 Fl,kFr2k+1,k,所以整个区间的最值就是这两段中大的那一个。

int ST(int l,int r){
	int k=log(r-l+1)/log(2);
	return max(f[l][k],f[r-(1<<k)+1][k]);
}

Example

这里以Luogu P3865为例。
一道模版题,直接看代码就行。

#include<bits/stdc++.h>
using namespace std;
long long n,m,a[100005],l,r,f[100005][155];
int ST(int l,int r){
	int k=0;
	while(l+(1<<k+1)-1<=r){
		k++;
	}
	return max(f[l][k],f[r-(1<<k)+1][k]);
}
int main(){
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		cin>>a[i];
	}
	for(int i=1;i<=n;i++){
		f[i][0]=a[i];
	}
	for(int j=1;(1<<j)<=n;j++){
		for(int i=1;i+(1<<j)-1<=n;i++){
			f[i][j]=max(f[i][j-1],f[i+(1<<(j-1))][j-1]);
		}
	}
	for(int i=1;i<=m;i++){
		cin>>l>>r;
		cout<<ST(l,r)<<'\n';
	}
	return 0;
}
posted @   Adventurer_XIV  阅读(57)  评论(2编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具
点击右上角即可分享
微信分享提示