浅谈 倍增/ST表
命题描述
给定一个长度为 \(n\) 的序列,\(m\) 次询问区间最大值
分析
上面的问题肯定可以暴力对吧。
但暴力肯定不是最优对吧,所以我们直接就不考虑了。。。
于是引入:倍增
首先,倍增是个什么东西?
在这里转一篇写的超棒的blog,点我。要是这都没看懂你就连小白兔都不如我就无语了。
总的来说,其实就是倒着运用二分的思想,从需求小的慢慢倍增把答案更新到需求大的
ST表就是一种常见的倍增思想的运用
关于ST表
ST表和树状数组,线段树这两种算法一样,是一种用于解决 \(RMQ(Range Minimum/Maximum Query)\)多次区间查询问题的离线算法
ST表的主要思想是构建一个二维数组 \(st[i][j]\),这个二维数组表示需要查询的数组的从下标 \(i\) 到下标 \(i + 2^{j - 1}\) 的最值,这里以最大值为例。超像 \(dp\) 的说~
我们可以把 \([i, j]\) 拆成数量相等的两半,在求出这两部分的最大值即可,故:
st[i][j] = max(st[i][j - 1], st[i + (1 << (j - 1))][j - 1];
再枚举一下 \(i, j\) 就可以了。点儿都不高级
接下来,该怎么实现查询呢?
如果查询的区间长度刚好是 \(2^k(k为整数)\),直接输出 \(st[l][log(r - l + 1) / log(2)]\) 即可;
如果不是,也很简单,我们还是将所给区间分为两部分。
首先规定在 \(st[i][j]\) 中 \(i = l\),\(j = k\),区间长度 \(len = r - l + 1\)。
会发现最大的\(k\) 应满足 \(2^k <= len\) (这样以 \(l\) 开头的ST表数据覆盖需要查询的区间中的数最多)
所以 \(k = (int) (log(len)/log(2))\)
显然查询时的区间 \([l,r]\) 分成的右边部分的左端点 \(x = r + 1 - 2^p\)
具体实现
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;
const int MAXN = 100005;
int st[MAXN][41];
void read(int &a) { // 读优
int k = 1;
a = 0;
char s = getchar();
while(s < '0' || s > '9') {
if(s == '-') k = -1;
s = getchar();
}
while(s >= '0' && s <= '9') {
a = a * 10 + (s - '0');
s = getchar();
}
a *= k;
}
int main() {
int n, m;
read(n); read(m);
for(int i = 1; i <= n; i++) read(st[i][0]);
for(int j = 1; j <= (int)(log(n) / log(2)); 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]);
for(int i = 1; i <= m; i++) {
int l, r;
read(l); read(r);
int k = (int)(log(r - l + 1) / log(2));
printf("%d\n", max(st[l][k], st[r - (1 << k) + 1][k]));
}
return 0;
}
浅谈 倍增/ST表的更多相关文章
- 浅谈对ST表的一些理解
今天打了人生第一道ST表题(其实只是ST表跑得最快); ST表是一种用来解决RMQ问题的利器... 大体操作有两步: 第一部分nlogn预处理 第二部分O(1)询问 预处理就是运用倍增+区间动规 ST ...
- P7599-[APIO2021]雨林跳跃【二分,倍增,ST表】
正题 题目链接:https://www.luogu.com.cn/problem/P7599 题目大意 \(n\)棵树,在某棵树上时可以选择向左右两边第一棵比它高的树跳,现在\(q\)次询问从\([A ...
- 【BZOJ1047】[HAOI2007]理想的正方形 (倍增ST表)
[HAOI2007]理想的正方形 题目描述 有一个\(a*b\)的整数组成的矩阵,现请你从中找出一个\(n*n\)的正方形区域,使得该区域所有数中的最大值和最小值的差最小. 输入输出格式 输入格式: ...
- 浅谈倍增LCA
题目链接:https://www.luogu.org/problemnew/show/P3379 刚学了LCA,写篇blog加强理解. LCA(Least Common Ancestors),即最近公 ...
- 【编程学习】浅谈哈希表及用C语言构建哈希表!
哈希表:通过key-value而直接进行访问的数据结构,不用经过关键值间的比较,从而省去了大量处理时间. 哈希函数:选择的最主要考虑因素--尽可能避免冲突的出现 构造哈希函数的原则是: ①函数本身便于 ...
- Sql server 浅谈用户定义表类型
1.1 简介 SQL Server 中,用户定义表类型是指用户所定义的表示表结构定义的类型.您可以使用用户定义表类型为存储过程或函数声明表值参数,或者声明您要在批处理中或在存储过程或函数的主体中使用的 ...
- 浅谈MySQL分表
关于分表:顾名思义就是一张数据量很大的表拆分成几个表分别进行存储. 我们先来大概了解以下一个数据库执行SQL的过程: 接收到SQL --> 放入SQL执行队列 --> 使用分析器分解SQL ...
- poj 3264 倍增 ST表
#include<iostream> #include<cmath> using namespace std; ; int a[maxn]; ]; ]; int quick(i ...
- 图书管理(Loj0034)+浅谈哈希表
图书管理 题目描述 图书管理是一件十分繁杂的工作,在一个图书馆中每天都会有许多新书加入.为了更方便的管理图书(以便于帮助想要借书的客人快速查找他们是否有他们所需要的书),我们需要设计一个图书查找系统. ...
随机推荐
- 专题三:redis的数据类型之hash
一.基本介绍 前面一个专题我们讲到string去存储明星微博粉丝数,微博数等,大概介绍了两种方式: set user:id:012345:fans 12210862 set u ...
- Cobalt Strike使用的一些技巧
利用msf模块上线beacon shell 当通过CS的mimikatz或者其他方式获得了目标机器的明文密码或者哈希时,可以利用metasploit的psexec_command模块来上线CS的bea ...
- FastThreadLocal 是什么鬼?吊打 ThreadLocal 的存在!!
ThreadLocal 大家都知道是线程本地变量,今天栈长再介绍一个神器:FastThreadLocal,从字面上看就是:Fast + ThreadLocal,一个快的 ThreadLocal?这到底 ...
- Git的介绍及使用
一.配置用户信息: 配置用户名和邮箱: $ git config --global user.name "chunyu" $ git config --global user.em ...
- yaf拓展安装步骤
1.wget http://pecl.php.net/get/yaf-3.0.7.tgz //下载yaf.tar 2.tar zxvf yaf-3.0.7.tgz //解压 3.cd yaf-3.0. ...
- linux中配置yum文件
yum简介:yum的宗旨是自动化地升级,安装/移除rpm包,收集rpm包的相关信息,检查依赖性并自动提示用户解决. yum的关键之处是要有可靠的repository,顾名思义,这是软件的仓库,它可以是 ...
- 内网渗透 day4-meterpreter基本命令
meterpreter基本命令 目录 1.getuid 查看当前用户 1 2.getpid 查看当前的进程id 1 3.getsystem 初步提权 1 4.ps 1.查看进程列表2.帮助我们获取pi ...
- php判断手机浏览器和pc浏览器
<?php public function is_mobile(){ // returns true if one of the specified mobile browsers is det ...
- CSS3之transition属性
transition属性可直译为"过渡",主要用于检索或设置对象变换的过渡. 语法: transition:property duration [timing-function] ...
- Docker(33)- 如何修改 docker 容器的端口映射
如果你还想从头学起 Docker,可以看看这个系列的文章哦! https://www.cnblogs.com/poloyy/category/1870863.html 问题背景 docker run ...