专栏文章
ST表
算法·理论参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @miqa9wbp
- 此快照首次捕获于
- 2025/12/04 01:31 3 个月前
- 此快照最后确认于
- 2025/12/04 01:31 3 个月前
-
前言
话说为啥讨论区没了不能愉快的学习灌水了ST表这种基础还没学我真是弱爆了 -
ST表的概念及实现
这也是一种倍增的应用倍增在OI的应用还是很多的ST表可以说是DP和倍增的完美结合首先要知道区间最大值是一个具有"可重复贡献"性质的问题这个性质是什么就是说如果用来求解的预处理区间有重叠部分这些区间的并是所求的区间最终计算出的答案就是正确的用式子咳血地表达一下就是说对于区间有子区间,则有了这个东西我们能干什么呢如果手动模拟一下容易发现我们能使用至多两个预处理过的区间来覆盖询问区间也就是说询问时的时间复杂度可以被降至在处理有大量询问的题目时十分有效具体实现如下令 表示区间 的最大值。显然 。根据定义式,第二维就相当于倍增的时候“跳了 步”依据倍增的思路,写出状态转移方程而对于每个询问可以分成两个部分和其中好了上代码
#include <cmath>
#include <iostream>
using namespace std;
int a[50001];
int f[50001][16];
int n;
void rmq_init() //建立: dp(i,j) = min{dp(i,j-1),dp(i+2^(j-1),j-1) O(nlogn)
{
for (int i = 1; i <= n; i++)
f[i][0] = a[i];
int k = floor(log((double)n) / log(2.0)); // C/C++取整函数ceil()大,floor()小
for (int j = 1; j <= k; j++)
for (int i = n; i >= 1; i--) {
if (i + (1 << (j - 1)) <=
n) // f(i,j) = min{f(i,j-1),f(i+2^(j-1),j-1)
f[i][j] = min(f[i][j - 1], f[i + (1 << (j - 1))][j - 1]);
}
}
int rmq(int i, int j) //查询:返回区间[i,j]的最小值 O(1)
{
int k = floor(log((double)(j - i + 1)) / log(2.0));
return min(f[i][k], f[j - (1 << k) + 1][k]);
}
int main() {
scanf("%d", &n);
for (int i = 1; i <= n; i++)
scanf("%d", &a[i]);
rmq_init();
printf("%d\n", rmq(2, 5));
}
相关推荐
评论
共 0 条评论,欢迎与作者交流。
正在加载评论...