博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
ST表
阅读量:5217 次
发布时间:2019-06-14

本文共 2141 字,大约阅读时间需要 7 分钟。

模板-ST表

题目背景

这是一道ST表经典题——静态区间最大值

请注意最大数据时限只有0.8s,数据强度不低,请务必保证你的每次查询复杂度为 O(1)

题目描述

给定一个长度为 N 的数列,和 M 次询问,求出每一次询问的区间内数字的最大值。

输入输出格式

输入格式:

第一行包含两个整数 N, M,分别表示数列的长度和询问的个数。

第二行包含 N 个整数(记为 ai),依次表示数列的第 ii 项。

接下来 M行,每行包含两个整数 li, ri,表示查询的区间为[li,ri]

输出格式:

输出包含 M行,每行一个整数,依次表示每一次询问的结果。

输入输出样例

输入样例#1: 
8 89 3 1 7 5 6 0 81 61 52 72 61 84 83 71 8
输出样例#1: 
99779879

说明

对于30%的数据,满足: 1N,M10

对于70%的数据,满足: 1N,M≤1e5

对于100%的数据,满足: 1N1e5,1M1e6,ai[0,1e9],1liriN

关于这道区间最值的题,很显然要用ST表吧。

那么,ST表是什么呢?

简单的说,ST表就是通过初始化的方式来求区间最值,从而达到建表复杂度为O(nlogn),查询复杂度只为O(1)!!!(不激动吗?)

但显然它也有一定的弊端,就是建表之后就不能再更改(其实也不是不行,大不了重新建一个呗(想想时间复杂度。。。)),这也确立了它的局限性。。。

好的那么我们该如何实现呢?

1.建表

先确定一件事:长度为1的区间最大值就是该数本身(显然吧)

我们想一想,如果要记录每一个区间的最值,那么我们就需要把每一个区间都扫一遍,时间复杂度可想而知。。。

那么我们该怎么办呢?

这里我们用到了一种思想(也属于一种算法):倍增!!!

在讲他之前,我们先定义一个二维数组p[j][i]表示从第i个数开始,长度为pow(2,j)的区间的最大值。

好的,你可能又要问倍增是什么?

倍增就是2的n次幂,其中n不断的变大,由于他的增长是2的指数级的,因此称之为倍增。

我们来想一个问题:对于任意一个区间,他的最大值是不是就等于((它的分出的各个区间的最大值)的最大值)(好吧,有点绕)。。。

这个是显然的吧。。。

那么,我们是不是可以将它分为各个区间呢?(问题的关键)

再结合倍增,我们可以把一个区间[i,i+pow(2,j)-1]表示为[i,i+pow(2,j-1)-1]和[i+pow(2,j-1),i+pow(2,j)-1];(由此我们得到了状态转移方程;dp的出现了)

或许这张图会更明白一些。。。

因此,只要不断进行拆分,就可以利用倍增来初始化ST表。(没听懂没有关系,请再看一遍后继续往下听)

那么代码该如何实现呢?

其实也比较简单,只要从j=1开始倍增(j=0上文提到初始化的方法),并保证不要越界(如果越界就会RE或者加入一些十分奇怪的数。。。),再比较两个区间的最大值即可。

2.查询

刚刚讲的建表其实也是为了查询做准备工作,可能大家刚刚有一个疑问:不是要求区间最大值么?你怎么保证数据给的长度就正好是2的n次幂呢?

没事,我学的时候也有这一个疑问,因此我们还有下文qwq

你想,我们求的只是区间最大值,而不是区间之和,是不是有一点思路了呢?

没有也没关系,我们还是用一张图来解释一下:

看完这张图你可能有一个疑问:这个区间不是重叠了么?

但是这又有什么影响呢?

由于我们知道每一个点开始2的n次幂的区间最值,所以我们只要将所求区间用这个初始值完全覆盖即可,并且我们不能超出这个区间。

所以我们只要从两个边界点向区间里看,从大到小倍减直到找到第一个2的n次幂小于区间长度,显然它大于区间的一半,我们只要将[l,l+pow(2,k)-1]和[r-pow(2,k)+1]进行比较求出最值即可。

最后,附上本题代码:

1 #include
2 #include
3 #include
4 using namespace std; 5 int a[100005],p[50][100005]; 6 void start(int n) 7 { 8 int t=log2(n); 9 for(int k=1; k<=t+1; k++)10 {11 for(int i=1; i+(1<
<=n; i++)12 {13 p[k][i]=max(p[k-1][i],p[k-1][i+(1<<(k-1))]);14 }15 }16 }17 void query(int l,int r)18 {19 int t=log2(r-l+1);20 printf("%d\n",max(p[t][l],p[t][r-(1<

 

转载于:https://www.cnblogs.com/yufenglin/p/10305370.html

你可能感兴趣的文章
20.核心初始化之异常向量表
查看>>
[BSGS][哈希]luogu P3846 可爱的质数
查看>>
Python 第四十五章 MySQL 内容回顾
查看>>
iostat参数说明
查看>>
js 封装获取元素的第一个元素
查看>>
iOS 获取Home键指纹验证
查看>>
Python-Mac 安装 PyQt4
查看>>
P2571 [SCOI2010]传送带
查看>>
哈希表1
查看>>
用Data Url (data:image/jpg;base64,)将小图片生成数据流形式
查看>>
实验2-2
查看>>
C#初识
查看>>
String,StringBuffer与StringBuilder的区别?? .
查看>>
JavaScript(三) 数据类型
查看>>
移动端rem布局屏幕适配插件(放js中便可使用)
查看>>
Docker
查看>>
bzoj2259 [Oibh]新型计算机
查看>>
对位与字节的深度认识
查看>>
C++编程基础二 16-习题4
查看>>
MongoDB遇到的疑似数据丢失的问题。不要用InsertMany!
查看>>