ST表的原理及其实现
ST表类似树状数组,线段树这两种算法,是一种用于解决RMQ(Range Minimum/Maximum Query,即区间最值查询)问题的离线算法
与线段树相比,预处理复杂度同为O(nlogn),查询时间上,ST表为O(1),线段树为O(nlogn)
st表的主体是一个二维数组st[i][j],表示需要查询的数组的从下标i到下标i+2^j - 1的最值,这里以最小值为例
预处理函数:
int a[];//原始输入数组
int st[][];//st表 void init(int n)
{
for (int i = ; i < n; i++)
st[i][] = a[i]; for (int j = ; ( << j) <= n; j++)
{
for (int i = ; i + ( << j) - < n; i++)
st[i][j] = min(st[i][j - ],st[i + ( << (j - ))][j - ]);
}
}
这里首先把从0~n-1的2^0部分进行覆盖,再往下继承
继承这里也很好理解,我们以一个长度为5的数组[5,1,2,3,4]为例
2^0部分覆盖过去自然是5,4,3,2,1
2^1部分的长度为4,从0一直到3,因为从下标为4开始后面只有他自己
st[0][1]是下标为0~1的最小值,自然也就是st[0][0]和st[1][0]的最值
以此往下类推我们可以得出结论:
st[i][j] = min(st[i][j - 1],st[i + 2^(j - 1))][j - 1])
到这里初始化就完成了,注意下标不要越界,如果你对为什么这么处理有困惑的话,请继续看查询
查询函数这里不太好理解
初始化时,每一个状态对应的区间长度都为2^j,由于给出的查询区间长度不一定恰好为2^j,
所以我们要引出一个定理:2^log(a)>a/2 。
https://blog.csdn.net/Hanks_o/article/details/77547380 这里有一段非常非常好理解的解释,这里超级感谢原作者,我本人不能做出更好的解释,他的讲解是这样的:
这个很简单,因为log(a)表示小于等于a的2的最大几次方。
比如说log(4)=2,log(5)=2,log(6)=2,log(7)=2,log(8)=3,log(9)=3…….
那么我们要查询x到y的最小值。
设len=y-x+1,t=log(len)
根据上面的定理:2^t>len/2
从位置上来说,x+2^t越过了x到y的中间!
因为位置过了一半
所以x到y的最小值可以表示为min(从x往后2^t的最小值,从y往前2^t的最小值)
前面的状态表示为mn[t][x]
设后面(从y往前2^t的最小值)的初始位置是k,
那么k+2^t-1=y,所以k=y-2^t+1
所以后面的状态表示为mn[t][y-2^t+1]
所以x到y的最小值表示为min(mn[t][x],mn[t][y-2^t+1]),所以查询时间复杂度是O(1)
查询函数:
int search(int l, int r)
{
int k = (int)(log((double)(r - l + )) / log(2.0));
return min(st[l][k],st[r - ( << k) + ][k]);
}
示例程序:
#include <iostream>
#include <algorithm> using namespace std; int a[];//原始输入数组
int st[][];//st表 void init(int n)
{
for (int i = ; i < n; i++)
st[i][] = a[i]; for (int i = ; ( << i) <= n; i++)
{
for (int j = ; j + ( << i) - < n; j++)
st[j][i] = min(st[j][i - ],st[j + ( << (i - ))][i - ]);
}
} int search(int l, int r)
{
int k = (int)(log((double)(r - l + )) / log(2.0));
return min(st[l][k],st[r - ( << k) + ][k]);
} int main()
{
int n,m;
while (cin >> n >> m)
{
for (int i = ; i < n; i++)
cin >> a[i]; init(n); while (m--)
{
int l, r;
cin >> l >> r;
cout << search(l,r) << endl;;
}
}
return ;
}
这里有一个HDU3183的例题大家可以移步看一下具体的使用
https://www.cnblogs.com/qq965921539/p/9609015.html
ST表的原理及其实现的更多相关文章
- ST表
ST表的原理及其实现 ST表类似树状数组,线段树这两种算法,是一种用于解决RMQ(Range Minimum/Maximum Query,即区间最值查询)问题的离线算法 与线段树相比,预处理复杂度同为 ...
- ST表与树状数组
ST表 st表可以解决区间最值的问题.可以做到O(nlogn)预处理 ,O(1)查询,但是不支持修改. st表的大概思路就是用st[i][j]来表示从i开始的2的j次方个树中的最值,查询时就从左端点 ...
- hdu6107 倍增法st表
发现lca的倍增解法和st表差不多..原理都是一样的 /* 整篇文章分成两部分,中间没有图片的部分,中间有图片的部分 分别用ST表求f1,f2表示以第i个单词开始,连续1<<j行能写多少单 ...
- ST表学习总结
前段时间做16年多校联合赛的Contest 1的D题(HDU 5726)时候遇到了多次查询指定区间的gcd值的问题,疑惑于用什么样的方式进行处理,最后上网查到了ST表,开始弄得晕头转向,后来才慢慢找到 ...
- 【BZOJ3784】树上的路径 点分治序+ST表
[BZOJ3784]树上的路径 Description 给定一个N个结点的树,结点用正整数1..N编号.每条边有一个正整数权值.用d(a,b)表示从结点a到结点b路边上经过边的权值.其中要求a< ...
- ST表基础模板
ST表是用来求RMQ问题(求区间最大或最小值问题)的实用数据结构,支持\(O(nlog_n)\)建立,\(O(1)\)查询,是比较高效的结构 其原理实质上是DP(我最讨厌的东西) 题面:屠龙宝刀... ...
- 区间最值的优秀数据结构---ST表
ST表,听起来高大上,实际上限制非常多,仅仅可以求最值问题: 为什么?先从原理看起: st表运用了倍增的思想:st[i][j] = min(st[i][j - 1],st[i + 2^(j - 1)) ...
- POJ3693 Maximum repetition substring [后缀数组 ST表]
Maximum repetition substring Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 9458 Acc ...
- 【BZOJ-2006】超级钢琴 ST表 + 堆 (一类经典问题)
2006: [NOI2010]超级钢琴 Time Limit: 20 Sec Memory Limit: 552 MBSubmit: 2473 Solved: 1211[Submit][Statu ...
随机推荐
- python学习 day20 (3月27日)----(单继承多继承c3算法)
继承: 提高代码的重用性,减少了代码的冗余 这两个写法是一样的 Wa('青蛙').walk() #青蛙 can walk wa = Wa('青蛙') wa.walk() #青蛙 can walk 1. ...
- 2019.01.16 bzoj3526: [Poi2014]Card(线段树)
传送门 线段树菜题. 题意:有一些卡牌,正反各有一个数,你可以任意翻转,每次操作会将两张卡牌的位置调换,你需要在每次操作后回答以现在的卡牌顺序能否通过反转形成一个单调不降的序列. 思路: 对于一个线段 ...
- Java中各类Cache机制实现解决方案[来自CSDN]
摘要:在Java中,不同的类都有自己单独的Cache机制,实现的方法也可能有所不同,文章列举了Java中常见的各类Cache机制的实现方法,同时进行了综合的比较. 在Java中,不同的类都有自己单独的 ...
- Codeforces Round #541 (Div. 2) D 并查集 + 拓扑排序
https://codeforces.com/contest/1131/problem/D 题意 给你一个n*m二维偏序表,代表x[i]和y[j]的大小关系,根据表构造大小分别为n,m的x[],y[] ...
- spring mvc 文件上传工具类
虽然文件上传在框架中,已经不是什么困难的事情了,但自己还是开发了一个文件上传工具类,是基于springmvc文件上传的. 工具类只需要传入需要的两个参数,就可以上传到任何想要上传的路径: 参数1:Ht ...
- nginx 下载 大文件被截断
如果出现大文件被截断,且ngix的日志大量出现以下类似报错: 则说明是nginx没有fastcgi_temp的读写权限.其中fastcgi_temp是自己的文件夹名称,每个人的不同且路径也会不同,这个 ...
- FPGA速度等级
转自http://wenku.baidu.com/view/ea793deef8c75fbfc77db263.html?from=rec 最初接触speed grade这个概念时,很是为Altera的 ...
- 20155205 2016-2017-2 《Java程序设计》第9周学习总结
20155205 2016-2017-2 <Java程序设计>第9周学习总结 教材学习内容总结 第十六章 JDBC简介 厂商在实现JDBC驱动程序时,依方式可将驱动程序分为四种类型: JD ...
- 20155205 2016-2017-2 《Java程序设计》第2周学习总结
20155205 2016-2017-2 <Java程序设计>第2周学习总结 教材学习内容总结 变量 变量在命名时有一些规则,它不可以使用数字作为开头,也不可以使用特殊字符. 对常用忽略符 ...
- 一些js在线引用文档
1.jquery在线引用: <script src="https://code.jquery.com/jquery-3.1.1.min.js"></script& ...