POJ 3264 Balanced Lineup (RMQ问题)

本文介绍使用ST算法解决区间最值查询(RMQ)问题的方法。ST算法能在O(n log n)时间内预处理出固定长度区间的最值,查询时可快速得到任意区间最值。文中提供了一个具体的C++实现示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最简单的RMQ问题,这次改用ST算法来写,存下来当模板吧。

ST算法通过nlogn的时间(也可以是O(n))预处理出d[i][j](起始位置为i长度为2^(j-1))区间的内的最值,递推式:d[i][j] = min(d[i][j-1],d[I+2^(j-1][j-1])

查询的时候先找到一个k有2^(k+1)>(R-L+1)然后可得minv(L,R)=min(d[L][K],d[R-(1<<K)+1][k])中间有些元素可能重复判断了,不过求最值问题不需要考虑这些。

 

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 50001;
int minv[maxn][20],maxv[maxn][20],n,val[maxn],q;
void init_RMQ() {
	for (int i = 0; i < n; i++) minv[i][0] = maxv[i][0] = val[i];
	for (int j = 1; (1 << j) <= n; j++) {
		for (int i = 0; i + (1 << j) < n + 1; i++) {
			maxv[i][j] = max(maxv[i][j - 1], maxv[i + (1 << (j - 1))][j - 1]);
			minv[i][j] = min(minv[i][j - 1], minv[i + (1 << (j - 1))][j - 1]);
		}
	}
}
int main() {
	scanf("%d%d", &n, &q);
	for (int i = 0; i < n; i++) scanf("%d", val + i);
	init_RMQ();
	int a, b;
	for (int i = 0; i < q; i++) {
		scanf("%d%d", &a, &b); a--; b--;
		int k = 0;
		while ((1 << (k + 1)) <= b - a + 1) k++;
		printf("%d\n", max(maxv[a][k], maxv[b - (1 << k) + 1][k]) - min(minv[a][k], minv[b - (1 << k) + 1][k]));
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值