古典叙事 · 技术札记

序章

山河有卷
人间有声

写代码,也写长风、旧城与未熄的灯。
愿每一篇随笔,都有自己的山水与回声。
阅览随笔

ST表

ST表

定义

st表是一种基于倍增思想的高级数据结构,对于区间查询最大值与最小值,可以达到o(1)的复杂度,预处理的复杂度为(nlogn)

模板题

https://www.luogu.com.cn/problem/P3865
题目大意:给定m个查询,每次找出区间(l,r)中的最大值
采用倍增的思想
用dp[i][j]表示区间(i,i+pow(2,j)-1)的最大值,dp[i][0]等于a[i];
所以dp[i][j]=max(dp[i][j-1],dp[dp[i][j-1]][j-1]);
伪代码

for(int i=1;i<=lg[n];i++)
	{
		for(int j=1;j+(1<<i)<=n+1;j++)
		{
			dp[j][i] = max(dp[j][i - 1], dp[j + (1 << i - 1)][i-1]);
		}
	}

接下来处理查询,对于每个查询(l,r),定义s=log2(r-l+1),我们查找dp[l][s]与dp[r-1<<s+1][s]中的最大值即为答案

AC代码
#include <iostream>
#include <stack>
#include <algorithm>
#include <cmath>
using namespace std;
using i64 = long long;
i64 n,m, lg[1000005];
stack <i64> w;
i64 num = 0;
i64 dp[100005][25];
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;
}
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	cin >> n >> m;
	lg[1] = 0;
	for(int i=2;i<=n;i++)
	{
		lg[i] = lg[i >> 1] + 1;
	}
	for(int i=1;i<=n;i++)
	{
		cin >> dp[i][0];
	}
	for(int i=1;i<=lg[n];i++)
	{
		for(int j=1;j+(1<<i)<=n+1;j++)
		{
			dp[j][i] = max(dp[j][i - 1], dp[j + (1 << i - 1)][i-1]);
		}
	}
	for(int i=1;i<=m;i++)
	{
		int x, y;
		cin >> x >> y;
		i64 r = lg[y-x+1];
		printf("%lld\n", max(dp[x][r], dp[y - (1 << r) + 1][r]));
	}
}
posted @ 2025-08-11 18:09  Morphis‘  阅读(23)  评论(0)    收藏  举报

特别策划 · CINEMATIC NOTES

风沙与孤骑

风起塞外,
胜负在刀剑之前。

“把复杂拆成秩序,把未知写成答案。”
Morphis · 山河一卷 愿你从这里出发,仍能听见山风。 影像:farfarSébastien Goldberg / Unsplash