学习笔记 ST算法
【引子】RMQ (Range Minimum/Maximum Query)问题:
对于长度为n的数列A,回答若干询问RMQ(A,i,j)(i,j<=n),返回数列A中下标在i,j里的最小(大)值,也就是说,RMQ问题是指求区间最值的问题。
{方法}
【例】给定数组,询问区间最小值。(无修改)
(数据范围不用线段树)
【解】可以写一个线段树,但是预处理和查询的复杂度都是O(logn),存心的话可以给你卡掉。
所以采用ST算法,它可以做到O(nlogn)的预处理,O(1)地回答每个询问
f[i][j]表示数组p从位置i开始到位置i+2^j-1的最小值
f[i][j]=min(f[i+(1<<(j-1))][j-1],f[i][j-1]);f[i][0]=p[i].
求a~b的最小值,就是找出比b-a+1小的最大的二的幂次k
有ans=min(f[a][k],f[b-(1<<k)+1][k])
【原理】
nlogn预处理出Min[][]和Max[][],查询的时候O(1)查询。
Max[j][i]或Min[j][i]代表,从j的位置开始,长度为2^i的子段中的最大值或最小值。
然后预处理的时候递推。
询问的时候先算出[l,r]的长度的2的对数,然后取出答案即可。
是一种优秀的存取方法。
【实现】(以最大值为例):
首先是预处理,用一个DP解决。设a[i]是要求区间最值的数列,f[i,j]表示从第i个数起连续2^j个数中的最大值。例如数列3 2 4 5
6 8 1 2 9 7
,f[1,0]表示第1个数起,长度为2^0=1的最大值,其实就是3这个数。
f[1,2]=5,f[1,3]=8,f[2,0]=2,f[2,1]=4……从这里可以看出f[i,0]其实就等于a[i]。这样,Dp的状态、初值都
已经有了,剩下的就是状态转移方程。我们把f[i,j]平均分成两段(因为f[i,j]一定是偶数个数字),从i到i+2^(j-1)-1为一
段,i+2^(j-1)到i+2^j-1为一段(长度都为2^(j-1))。用上例说明,当i=1,j=3时就是3,2,4,5
和
6,8,1,2这两段。f[i,j]就是这两段的最大值中的最大值。于是我们得到了动规方程F[i,j]=max(F[i,j-1],F[i+2^(j-
i),j-1]).
接下来是得出最值,也许你想不到计算出f[i,j]有什么用处,想计算max还是要O(logn),甚至O(n)。但有一个很好的办法,做到了
O(1)。还是分开来。如在上例中我们要求区间[2,8]的最大值,就要把它分成[2,5]和[5,8]两个区间,因为这两个区间的最大值我们可以直接由
f[2,2]和f[5,2]得到。扩展到一般情况,就是把区间[l,r]分成两个长度为2^n的区间(保证有f[i,j]对应)
【模板代码】
- #include<iostream>
- #include<cstdio>
- #include<cstring>
- #include<cmath>
- #include<algorithm>
- #include<queue>
- #include<cstdlib>
- #include<iomanip>
- #include<cassert>
- #include<climits>
- #define maxn 100001
- #define F(i,j,k) for(int i=j;i<=k;i++)
- #define M(a,b) memset(a,b,sizeof(a))
- #define FF(i,j,k) for(int i=j;i>=k;i--)
- #define inf 0x7fffffff
- #define maxm 21
- using namespace std;
- int read(){
- int x=,f=;char ch=getchar();
- while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
- while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
- return x*f;
- }
- int fm[maxn][maxm],fi[maxn][maxm],p[maxn];
- int n,q;
- inline int init()
- {
- cin>>n>>q;
- F(i,,n){
- cin>>p[i];
- }
- F(i,,n){
- fm[i][]=fi[i][]=p[i];
- }
- int m=floor((int)(log10((double)n)/log10((double))));
- F(j,,m)F(i,,n){
- fm[i][j]=max(fm[i+(<<(j-))][j-],fm[i][j-]);
- fi[i][j]=min(fi[i+(<<(j-))][j-],fi[i][j-]);
- }
- }
- inline int stmax(int a,int b)
- {
- int m=floor((int)(log10((double)(b-a+))/log10((double))));
- return max(fm[a][m],fm[b-(<<m)+][m]);
- }
- inline int stmin(int a,int b)
- {
- int m=floor((int)(log10((double)(b-a+))/log10((double))));
- return min(fi[a][m],fi[b-(<<m)+][m]);
- }
- int main()
- {
- std::ios::sync_with_stdio(false);//cout<<setiosflags(ios::fixed)<<setprecision(1)<<y;
- // freopen("data.in","r",stdin);
- // freopen("data.out","w",stdout);
- init();int c,d;
- while(q--)
- {
- int a,b;
- cin>>a>>b;
- if(a>b) swap(a,b);
- c=stmax(a,b);
- d=stmin(a,b);
- cout<<c<<endl<<d<<endl;
- }
- return ;
- }
ST
学习笔记 ST算法的更多相关文章
- [ML学习笔记] XGBoost算法
[ML学习笔记] XGBoost算法 回归树 决策树可用于分类和回归,分类的结果是离散值(类别),回归的结果是连续值(数值),但本质都是特征(feature)到结果/标签(label)之间的映射. 这 ...
- 学习笔记 - Manacher算法
Manacher算法 - 学习笔记 是从最近Codeforces的一场比赛了解到这个算法的~ 非常新奇,毕竟是第一次听说 \(O(n)\) 的回文串算法 我在 vjudge 上开了一个[练习],有兴趣 ...
- 学习笔记——EM算法
EM算法是一种迭代算法,用于含有隐变量(hidden variable)的概率模型参数的极大似然估计,或极大后验概率估计.EM算法的每次迭代由两步组成:E步,求期望(expectation):M步,求 ...
- 数据挖掘学习笔记--AdaBoost算法(一)
声明: 这篇笔记是自己对AdaBoost原理的一些理解,如果有错,还望指正,俯谢- 背景: AdaBoost算法,这个算法思路简单,但是论文真是各种晦涩啊-,以下是自己看了A Short Introd ...
- 学习笔记-KMP算法
按照学习计划和TimeMachine学长的推荐,学习了一下KMP算法. 昨晚晚自习下课前粗略的看了看,发现根本理解不了高端的next数组啊有木有,不过好在在今天系统的学习了之后感觉是有很大提升的了,起 ...
- Java学习笔记——排序算法之快速排序
会当凌绝顶,一览众山小. --望岳 如果说有哪个排序算法不能不会,那就是快速排序(Quick Sort)了 快速排序简单而高效,是最适合学习的进阶排序算法. 直接上代码: public class Q ...
- Java学习笔记——排序算法之进阶排序(堆排序与分治并归排序)
春蚕到死丝方尽,蜡炬成灰泪始干 --无题 这里介绍两个比较难的算法: 1.堆排序 2.分治并归排序 先说堆. 这里请大家先自行了解完全二叉树的数据结构. 堆是完全二叉树.大顶堆是在堆中,任意双亲值都大 ...
- Java学习笔记——排序算法之希尔排序(Shell Sort)
落日楼头,断鸿声里,江南游子.把吴钩看了,栏杆拍遍,无人会,登临意. --水龙吟·登建康赏心亭 希尔算法是希尔(D.L.Shell)于1959年提出的一种排序算法.是第一个时间复杂度突破O(n²)的算 ...
- 学习笔记——SM2算法原理及实现
RSA算法的危机在于其存在亚指数算法,对ECC算法而言一般没有亚指数攻击算法 SM2椭圆曲线公钥密码算法:我国自主知识产权的商用密码算法,是ECC(Elliptic Curve Cryptosyste ...
随机推荐
- Web前端开发最佳实践(2):前端代码重构
前言 代码重构是业内经常讨论的一个热门话题,重构指的是在不改变代码外部行为的情况下进行源代码修改,所以重构之前需要考虑的是重构后如何才能保证外部行为不改变.对于后端代码来说,可以通过大量的自动化测试来 ...
- css去除chrome下select元素默认border-radius
在mac下的chrome,对于select元素会默认有一个border-radius,当然有些情况下并不需要圆角,所以就要去掉. 比较常用的方法是: .select { -webkit-appeara ...
- Hibernate 单项一对多的关联映射
在上一篇中我们简单介绍了多对一的关联映射,本文介绍hibernate中一对多的关联映射. 1.设计表结构 虽然关联关系由多对一变为一对多,但是我们表结构不会发生改变,只是指向变了. 2.创建stude ...
- 【BZOJ 3160】 3160: 万径人踪灭 (FFT)
3160: 万径人踪灭 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 1440 Solved: 799 Description Input Outp ...
- android studio 可以汉化的 文件 地方
韩梦飞沙 韩亚飞 313134555@qq.com yue31313 han_meng_fei_sha 汉化包 百度云盘 下载地址:https://pan.baidu.com/s/1pLjwy ...
- CSS 笔记——阴影、圆角、旋转、光标
7. 阴影.圆角.旋转.光标 (1)box-shadow 阴影 基本语法 text-shadow: h-shadow v-shadow blur color; box-shadow: h-shadow ...
- 【Pollard-rho算法】【DFS】poj2429 GCD & LCM Inverse
题意:给你一两个数m和n,它们分别是某对数A,B的gcd和lcm,让你求出一对使得A+B最小的A,B. n/m的所有质因子中,一定有一部分是只在A中的,另一部分是只在B中的. 于是对n/m质因子分解后 ...
- Eclipse下mallet使用的方法
Mallet是Umass大牛开发的一个关于统计自然语言处理的l的开源库,很好的一个东西.可以用来学topic model,训练ME模型等.对于开发者来说,其官网的技术文档是非常有效的. mallet下 ...
- ubuntu 关闭n卡
ubuntu对n卡支持不好,电脑耗电和发汤,把它关闭掉 #sudo add-apt-repository ppa:bumblebee/stable#sudo apt-get update#su ...
- CentOS 6.9/7通过yum安装指定版本的Nginx
说明:通过yum好处其实很多,环境变量不用配置,配置文件放在大家都熟悉的地方,通过rpm -ql nginx可以知道全部文件的地方等等. Nginx(1.12.2) 一.安装和配置 1.安装 # rp ...