想学习一下LCA倍增,先 水一个黄题 学一下ST表

ST表

介绍:

这是一个运用倍增思想,通过动态规划来计算区间最值的算法

算法步骤:

  1. 求出区间最值

  2. 回答询问

求出区间最值:

f[i][j]来存储从第 j 个点开始,向后 2 ^ i - 1 个点中的最值(包括本身)

利用二分法的思想,将区间 [ j,j +(2 ^ i)- 1 ] 平均(大概)分成两半

可以算出,区间 [ j,j +(2 ^ i)- 1 ] 的长度为 2 ^ i

所以一半的长度为 2 ^ i - 1

那么分成的两个区间就为 [ j,j +(2 ^(i - 1)- 1 ] 和 [ j +(2 ^ i - 1 ),j +(2 ^ i)- 1 ] 。

毫无疑问,

f[i][j] = max(f[i - 1][j],f[i - 1][j +(1 << i - 1)])

这样递推式就出来了

现在来想一下:

f[0][j]就是从 j 开始向后数第 2 ^ 0 - 1 个点的最值,区间为 [ j,j ]

不用考虑,f[0][j]就是第 j 个数本身

好了,现在边界也得出来了,可以开始 dp 了

上代码:

void prew() {
F1(i, 1, n) f[0][i] = a[i]; // 给边界赋值,a[i] 存的是数列的第 i 个数
int kf = log2(n); // 得出数列最多可以向后跳几个 2 的幂,n 为数列长度
F1(i, 1, kf) { // 枚举区间的长度 2 ^ i
for (int j = 1; j + (1 << i) - 1 <= n; j++) // 枚举起点
f[i][j] = max(f[i - 1][j], f[i - 1][j + (1 << i - 1)]); // 递推式
}
}

回答询问:

由于 log2 运算可能会出现实数,而我们又用整数类型来存储,所以可能会出现两个区间不能完全覆盖整个区间的情况,得出的 f[i][j]不够精准

最简单的方法就是用两个区间覆盖

反正又没要求两个区间不能重叠~~

可以选用f[k][l]f[k][r-(1<<k)+1]来覆盖f[l][r]

所以f[l][r] = max(f[k][l],f[k][r -(1 << k)+ 1])(k 为区间 [l,r] 的长度的 log2)

再上代码:

int ask(int l, int r) {
int k = log2(r - l + 1); // 求出区间最大的 log2 值
return max(f[k][l], f[k][r - (1 << k) + 1]); // 返回区间 [l,r] 的最大值
}

完整代码:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <cmath>
#include <algorithm> // 妈妈再也不怕我的头文件不够使啦~~
#define MAXN 100100
#define INF 0x3f3f3f3f
#define LL long long
#define F1(i, a, b) for (LL i = a; i <= b; ++i) // 懒人必备神器
#define F2(i, a, b) for (LL i = a; i >= b; --i)
using namespace std; int f[31][MAXN], a[MAXN];
//f[i][j]表示从 j 往后 2 ^ i - 1 个数中的最大值
int n, m; inline int read() { // 快读
int sto = 0, fg = 1;
char ch = getchar();
while (ch < '0' || ch > '9') {
if (ch == '-') fg = -1;
ch = getchar();
}
while (ch >= '0' && ch <= '9') {
sto = (sto << 1) + (sto << 3) + (ch ^ 48);
ch = getchar();
}
return sto * fg;
} void prew() { // 预处理 dp
F1(i, 1, n) f[0][i] = a[i];
int kf = log2(n);
F1(i, 1, kf) {
for (int j = 1; j + (1 << i) - 1 <= n; j++)
f[i][j] = max(f[i - 1][j], f[i - 1][j + (1 << i - 1)]);
}
} int ask(int l, int r) { // 回答询问
int k = log2(r - l + 1);
return max(f[k][l], f[k][r - (1 << k) + 1]);
} int main()
{
int l, r, ans;
n = read(); m = read();
F1(i, 1, n) a[i] = read();
prew();
F1(i, 1, m) {
l = read(); r = read();
ans = ask(l, r);
printf("%d\n", ans);
}
return 0;
}

模板题:

洛谷P3865

【算法】ST表的更多相关文章

  1. 【基础算法-ST表】入门 -C++

    前言 学了树状数组看到ST表模板跃跃欲试的时候发现完全没思路,因为给出的查询的时间实在太短了!几乎是需要完成O(1)查询.所以ST表到底是什么神仙算法能够做到这么快的查询? ST表 ST表是一个用来解 ...

  2. 线段树(two value)与树状数组(RMQ算法st表)

    士兵杀敌(三) 时间限制:2000 ms  |  内存限制:65535 KB 难度:5 描述 南将军统率着N个士兵,士兵分别编号为1~N,南将军经常爱拿某一段编号内杀敌数最高的人与杀敌数最低的人进行比 ...

  3. 浅谈ST表

    发现自己学的一直都是假的ST表QWQ. ST表 ST表的功能很简单 它是解决RMQ问题(区间最值问题)的一种强有力的工具 它可以做到$O(nlogn)$预处理,$O(1)$查询最值 算法 ST表是利用 ...

  4. ST表学习笔记

    ST表是一种利用DP思想求解最值的倍增算法 ST表常用于解决RMQ问题,即求解区间最值问题 接下来以求最大值为例分步讲解一下ST表的建立过程: 1.定义 f[i][j]表示[i,i+2j-1]这个长度 ...

  5. 浅谈 倍增/ST表

    命题描述 给定一个长度为 \(n\) 的序列,\(m\) 次询问区间最大值 分析 上面的问题肯定可以暴力对吧. 但暴力肯定不是最优对吧,所以我们直接就不考虑了... 于是引入:倍增 首先,倍增是个什么 ...

  6. LCA 算法(一)ST表

    介绍一种解决最近公共祖先的在线算法,st表,它是建立在线性中的rmq问题之上.   代码:   //LCA: DFS+ST(RMQ) #include<cstdio> #include&l ...

  7. 算法学习 - ST表 - 稀疏表 - 解决RMQ问题

    2017-08-26 21:44:45 writer:pprp RMQ问题就是区间最大最小值查询问题: 这个SparseTable算法构造一个表,F[i][j] 表示 区间[i, i + 2 ^ j ...

  8. [算法模板]ST表

    [算法模板]ST表 ST表和线段树一样,都能解决RMQ问题(范围最值查询-Range Minimum Query). 我们开一个数组数组\(f[maxn][maxn\log_2]\)来储存数据. 定义 ...

  9. 【算法学习笔记】RMQ问题与ST表

    \(0.\) RMQ问题 P1816 人话翻译 给定一个长度为\(n\)的数列\(a\),然后有\(m\)组询问,每次询问一个区间\([l,r]\)的最小值. 其中\(m,n\leq10^5\) \( ...

  10. 【JZOJ5064】【GDOI2017第二轮模拟day2】友好城市 Kosarajo算法+bitset+ST表+分块

    题面 在Byteland 一共有n 座城市,编号依次为1 到n,这些城市之间通过m 条单向公路连接. 对于两座不同的城市a 和b,如果a 能通过这些单向道路直接或间接到达b,且b 也能如此到达a,那么 ...

随机推荐

  1. 152. Maximum Product Subarray动态规划连乘最大子串

    Find the contiguous subarray within an array (containing at least one number)which has the largest p ...

  2. C语言I博客作业1

    1 .班级链接: https://edu.cnblogs.com/campus/zswxy/SE2020-3 2 .作业要求链接: https://edu.cnblogs.com/campus/zsw ...

  3. vue-element Form表单验证(表单验证没错却一直提示错误)

    在使用element-UI 的表单时,发生一个验证错误,例如已输入值但求验证纠错:       代码如下所示: <el-form :model="correction" :i ...

  4. JAVE JDK安装步骤

    1.安装JDK 选择安装目录 安装过程中会出现两次 安装提示 .第一次是安装 jdk ,第二次是安装 jre .建议两个都安装在同一个java文件夹中的不同文件夹中.(不能都安装在java文件夹的根目 ...

  5. 这些JS技巧,看看你是否都会用?

    问题1:以下代码在浏览器控制台上会打印什么? var a = 10; function foo() { console.log(a); // ?? var a = 20; } foo(); 问题2:如 ...

  6. 对接口报错404 发现url多了一些不可描述的代码%E2%80%8B

    接口url出现了空格,复制的url可能出现空格肉眼看不出来,手动输入一遍URL

  7. [ABP教程]第三章 创建、更新和删除图书

    Web应用程序开发教程 - 第三章: 创建,更新和删除图书 关于本教程 在本系列教程中, 你将构建一个名为 Acme.BookStore 的用于管理书籍及其作者列表的基于ABP的应用程序. 它是使用以 ...

  8. 壁球小游戏详解(附有源码.cpp)

    1.在python中安装pygame 2.将下列源码复制过去,运行. #引用 import pygame, sys #初始化 pygame.init() size = width, height = ...

  9. 为Github仓库添加Github Actions实现持续集成: Android apk自动编译发布以及github pages同步推送coding.net

    内容转载自我的博客 目录 说明 1. 编写Android项目的CI配置文件 2. 编写Jekyll项目的CI配置文件 2.1 配置coding.net 2.2 配置github 2.3 自动部署到co ...

  10. 安装Android Studio遇到的问题

    1. 学习视频 视频链接:https://www.bilibili.com/video/BV1jW411375J?p=2 2. Android Studio1.5.1的下载地址: http://www ...