ST表

主要用来快速查询静态数据区间最大值

思路

  • 数组\(A[i][j]\)存储数列\(\{a_i\}\)中区间\(i \in [i, i+2^j)\)的最大值

  • 查询时只需要查询\(max\{A[i][k], A[j-2^k+1][k]\}\)即可,保证\(2\times2^k \geq j - i\)即可

  • 预处理使用动态规划的思想

  • 位运算勤加括号!

  • 位运算勤加括号!!

  • 位运算勤加括号!!!


P3865 【模板】ST表

题目背景

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

请注意最大数据时限只有0.8s,数据强度不低,请务必保证你的每次查询复杂度为 \(O(1)\)。若使用更高时间复杂度算法不保证能通过。

如果您认为您的代码时间复杂度正确但是 TLE,可以尝试使用快速读入:

  1. inline int read()
  2. {
  3. int x=0,f=1;char ch=getchar();
  4. while (!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();}
  5. while (isdigit(ch)){x=x*10+ch-48;ch=getchar();}
  6. return x*f;
  7. }

题目描述

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

输入格式

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

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

接下来 \(M\) 行,每行包含两个整数 \(l_i, r_i\),表示查询的区间为 \([ l_i, r_i]\)

输出格式

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

输入输出样例

输入 #1复制

  1. 8 8
  2. 9 3 1 7 5 6 0 8
  3. 1 6
  4. 1 5
  5. 2 7
  6. 2 6
  7. 1 8
  8. 4 8
  9. 3 7
  10. 1 8

输出 #1复制

  1. 9
  2. 9
  3. 7
  4. 7
  5. 9
  6. 8
  7. 7
  8. 9

说明/提示

对于\(30\%\)的数据,满足:$ 1 \leq N, M \leq 10$

对于\(70\%\)的数据,满足: \(1 \leq N, M \leq {10}^5\)

对于\(100\%\)的数据,满足: \(1 \leq N \leq {10}^5, 1 \leq M \leq 2 \times {10}^6, a_i \in [0, {10}^9], 1 \leq l_i \leq r_i \leq N\)

完整解答

  1. #include <ctype.h>
  2. #include <cstdio>
  3. #include <algorithm>
  4. #define MAXN 100000
  5. // 这里数组开成ST[25][MAXN]可提速
  6. int Log[MAXN + 10], ST[25][MAXN + 10], N, M, l, r;
  7. // 快速读取
  8. inline int read()
  9. {
  10. int x = 0, f = 1;char ch = getchar();
  11. while (!isdigit(ch)) { if (ch == '-') f = -1;ch = getchar(); }
  12. while (isdigit(ch)) { x = x * 10 + ch - 48;ch = getchar(); }
  13. return x * f;
  14. }
  15. // 初始化
  16. void init() {
  17. // log2预处理
  18. Log[1] = 0;
  19. for (int i = 2; i <= N + 1; i++) Log[i] = Log[i / 2] + 1;
  20. // ST表预处理
  21. for (int i = 1; i <= N; i++) ST[0][i] = read();
  22. for (int j = 1; (1 << j) <= N; j++)
  23. for (int i = 1; i + (1 << (j - 1)) <= N; i++)
  24. ST[j][i] = std::max(ST[j - 1][i], ST[j - 1][i + (1 << (j - 1))]);
  25. }
  26. int main() {
  27. N = read(); M = read();
  28. init();
  29. while (M--) {
  30. l = read(); r = read();
  31. int k = Log[r - l + 1];
  32. printf("%d\n", std::max(ST[k][l], ST[k][r - (1 << k) + 1]));
  33. }
  34. return 0;
  35. }

[数据结构与算法-13]ST表的更多相关文章

  1. [算法模板]ST表

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

  2. Java数据结构和算法 - 哈希表

    Q: 如何快速地存取员工的信息? A: 假设现在要写一个程序,存取一个公司的员工记录,这个小公司大约有1000个员工,每个员工记录需要1024个字节的存储空间,因此整个数据库的大小约为1MB.一般的计 ...

  3. COJ 1003 WZJ的数据结构(三)ST表

    WZJ的数据结构(三) 难度级别:B: 运行时间限制:3000ms: 运行空间限制:51200KB: 代码长度限制:2000000B 试题描述 请你设计一个数据结构,完成以下功能: 给定一个大小为N的 ...

  4. 数据结构与算法(c++)——跳跃表(skip list)

    今天要介绍一个这样的数据结构: 单向链接 有序保存 支持添加.删除和检索操作 链表的元素查询接近线性时间 ——跳跃表 Skip List 一.普通链表 对于普通链接来说,越靠前的节点检索的时间花费越低 ...

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

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

  6. [poj3264]rmq算法学习(ST表)

    解题关键:rmq模板题,可以用st表,亦可用线段树等数据结构 log10和log2都可,这里用到了对数的换底公式 类似于区间dp,用到了倍增的思想 $F[i][j] = \min (F[i][j - ...

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

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

  8. 【算法】ST表

    想学习一下LCA倍增,先 水一个黄题 学一下ST表 ST表 介绍: 这是一个运用倍增思想,通过动态规划来计算区间最值的算法 算法步骤: 求出区间最值 回答询问 求出区间最值: 用f[i][j]来存储从 ...

  9. 算法学习——st表

    st表是一种基于倍增思想的DP. 用于求一个数列中的某个区间的最大/最小值. 用st[i][j]表示从第i个开始往后2^j个点,最大的是多少. 我们令k[i]表示2^i等于多少 那么有转移方程 st[ ...

随机推荐

  1. 牛客小白月赛30 B.最好的宝石 (线段树)

    题意:RT. 题解:很明显的线段树维护区间最大值操作,但是我们同时还要维护最大值的个数,我们在build或者modify操作完子树然后push_up的时候,我们先从两个儿子取max更新父节点的最大值, ...

  2. UVA 10480 Sabotage (最大流) 最小割边

    题目 题意: 编写一个程序,给定一个网络规范和破坏每个连接的成本,确定要切断哪个连接,以便将首都和最大的城市分离到尽可能低的成本. 分割-------------------------------- ...

  3. Python 闭包及装饰器

    闭包是指延伸了作用域的函数. 自由变量(free variable) 指未在本地作用域中绑定的变量 函数装饰器用于在源码中标记函数, 以某种方式增强函数的行为. 装饰器实质,把被装饰的函数替换为新函数 ...

  4. read()、readline()、readlines() -- Python

    文本文件:readfile.txt 详细描述: read()                  #一次性读取文本中全部的内容,以字符串的形式返回结果 readline()           #只读取 ...

  5. 【一天一个基础系列】- java之泛型篇

    简介 说起各种高级语言,不得不谈泛型,当我们在使用java集合的时候,会发现集合有个缺点:把一个对象"丢进"集合之后,集合就会"忘记"这个对象的数据类型,当再次 ...

  6. cccc超级酱油心得

    第一次线下比赛献给了cccc. 大致写写自己心得,比赛前一天晚上日常和室友在宿舍玩到11点多,洗漱上床.睡前突然想起第二天还有比赛,顿时激动加紧张.在床上刷了刷知乎和百度,看几道去年的真题,熬到了12 ...

  7. linux多线程模拟银行家算法

    题外话: 这应该是最近有点难度的作业了,起码比之前的理发师,读写,哲学家问题要难. 但是做好程序的结构,自顶向下,就还是不难的. 银行家算法简介:                 代码: init() ...

  8. SDN总结

    之前做项目用到了SDN,知道其作用,但是对其不是特别熟悉,今天特来总结一下相关知识点: 1. SDN的典型架构分为哪三层 主要分为应用层,控制层,和基础设施层: 2. SDN技术的关键点是 控制平面和 ...

  9. 5分钟学Go 基础01:初识 Go 的第一印象是薪水可观

    本文首发于公众号「5分钟学Go」,一个让你每次花 5 分钟就能掌握一个技能点的公众号.目前在博主连更 5 分钟学Go系列,大家可以关注下,第一时间掌握Go技能.如果想要加群交流,可以在公众号后台回复「 ...

  10. Twitter 分享

    Twitter 分享 Twitter Share API https://twitter.com/intent/tweet?url= &text= demo ?url= https://www ...