C++稀疏表(Sparse Table,ST表)区间最小值/最大值查询 模板

前言:
在计算机科学领域,高效处理区间查询问题一直是算法设计的核心挑战之一。无论是在数据预处理、数据分析还是在线服务中,快速回答 “某个区间内的最大值 / 最小值是多少”“区间和是多少” 等问题,都对系统性能至关重要。稀疏表(Sparse Table,ST 表)作为一种经典的数据结构,凭借其O (n log n) 的预处理时间复杂度和O (1) 的单次查询时间复杂度,成为解决这类问题的理想选择。


解决什么问题

稀疏表常用于以下几种场景:
1.区间最小值/最大值查询(本文主要讲解这类问题)
2.均值和其他聚合统计的快速查询
3.处理静态数据集而需要频繁进行的查询操作

例题

在这里插入图片描述

思路

什么是ST表?

在这里插入图片描述

倍增的概念

“倍增”,简单来说就是成倍地增长。在算法设计中,它通过预先计算出一些具有特定长度(通常是 2 的幂次)的状态,然后利用这些状态快速组合出其他状态,从而在时间和空间上达到高效的处理效果。其核心在于利用 2 的幂次具有的可加性和二进制表示的特性,将原本需要逐步递推或遍历的过程进行优化。具体详情←

如何工作的?

在这里插入图片描述
在这里插入图片描述

模板

// 一句话题意:给定有 n 个数的序列,
// 和 m 次询问,求出每一次询问的区间内数字的最大值。

#include <iostream>
#include <cmath>
using namespace std;

#define MAXN 100002 // 最多1e5个元素
#define LOGN 17 // ceil(log2(MAXN))

int n, arr[MAXN]; // 存n个数的序列,下标从1开始
int st[MAXN][LOGN]; // st[i][j] 表示,从i开始的2^j个数和中最大的一个

// 构建st表,注意+优先于<<
void build_sparse_table() {
  for (int i = 1; i <= n; i++)
    st[i][0] = arr[i];
  
  for (int j = 1; (1<<j) <= n; j++)
    for (int i = 1; i+(1<<j)-1 <= n; i++)
      st[i][j] = max(st[i][j-1],st[i+(1<<(j-1))][j-1]);
}

// 查询区间[l,r]的最大值
int query(int l, int r) {
  int j = (int)log2(r-l+1);
  return max(st[l][j],st[r-(1<<j)+1][j]);
}

int main() {
  ios::sync_with_stdio(0);
  cin.tie(0); cout.tie(0);
  
  int m;
  cin >> n >> m;
  for (int i = 1; i <= n; i++)
    cin >> arr[i];
  
  build_sparse_table();

  while (m--) {
    int l, r; cin >> l >> r;
    cout << query(l,r) << '\n';
  }
  return 0;
}


稀疏表是一种高效的查询结构,利用预处理来加速对静态数据的区间查询。在 C++ 中实现稀疏表不仅可以提升算法性能,同时也给我们提供了一个灵活的模板结构,方便用户根据需求选取不同的列操作意图(如最小值、最大值等)。虽然它的构建过程相对复杂,但一次预处理后可以提供极为高效的查询结果,极大满足了算法在大量数据处理中的需求。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wangyuxuan1029

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值