区间最值的优秀数据结构---ST表
ST表,听起来高大上,实际上限制非常多,仅仅可以求最值问题;
为什么?先从原理看起;
st表运用了倍增的思想:st[i][j] = min(st[i][j - 1],st[i + 2^(j - 1))][j - 1]);
意义是:从i开始向后连续2^j个位置的最大值是,i开始向后连续2^(j-1)个位置的最大值和i+2^(j-1)开始向后连续2^(j-1)个位置的最大值;
好了,结构建立起来了,那么怎么查询呢?
一个公式:2^log(a)>a/2 。
所以说,查询(x,y)时我们设k=log(y-x+1);
ans=max(f[x][k],f[y-(1<<k)+1][k]);
现在我们知道了,ST表只能求最值的原因是它在查询时,为了节约时间复杂度而导致查询区间取并集操作;这样求区间和便无法得到正确答案;
附:1.求一维ST最值:
#include <bits/stdc++.h>
#define int long long
using namespace std;
int a[100010];
int f[100010][40],g[100010][40];
int n,q;
void build()
{
for(register int i=1;i<=n;i++){
f[i][0]=a[i];
g[i][0]=a[i];
}
for(register int j=1;(1<<j)<=n;j++){
for(register int i=1;(i+(1<<j)-1)<=n;i++){
f[i][j]=max(f[i][j-1],f[i+(1<<(j-1))][j-1]);
g[i][j]=min(g[i][j-1],g[i+(1<<(j-1))][j-1]);
}
}
}
int query(int x,int y)
{
int tmp=log2(y-x+1);
return max(f[x][tmp],f[y-(1<<tmp)+1][tmp])-min(g[x][tmp],g[y-(1<<tmp)+1][tmp]);
}
signed main()
{
scanf("%lld%lld",&n,&q);
for(register int i=1;i<=n;i++) scanf("%lld",&a[i]);
build();
for(register int i=1;i<=q;i++){
int x,y;
scanf("%lld%lld",&x,&y);
printf("%lld\n",query(x,y));
}
}
而二维st表原理就是将一个正方形分成了4份:
令 st[i][j][k]表示左上角为i,j,边长为k的正方形中的最大值。
st[i][j][k]=Max(st[i][j][k-1],st[i+(1<<k-1)][j][k-1],st[i][j+(1<<k-1)][k-1],st[i+(1<<k-1)][j+(1<<k-1)][k-1]);
查询时与一维ST表类似,取并集操作;
#include <bits/stdc++.h>
#define inc(i,a,b) for(register int i=a;i<=b;i++)
using namespace std;
int a,b,n;
int mmap[1001][1001];
int f[1001][1001][8],g[1010][1010][8];
void build()
{
inc(i,1,a){
inc(j,1,b){
f[i][j][0]=mmap[i][j];
g[i][j][0]=mmap[i][j];
}
}
for(int k=1;k<=7;k++){
for(int i=1;i+(1<<k)-1<=a;i++){
for(int j=1;j+(1<<k)-1<=b;j++){
f[i][j][k]=max(f[i+(1<<k-1)][j+(1<<k-1)][k-1],f[i+(1<<k-1)][j][k-1]);
f[i][j][k]=max(f[i][j][k],f[i][j+(1<<k-1)][k-1]);
f[i][j][k]=max(f[i][j][k],f[i][j][k-1]);
g[i][j][k]=min(g[i+(1<<k-1)][j+(1<<k-1)][k-1],g[i+(1<<k-1)][j][k-1]);
g[i][j][k]=min(g[i][j][k],g[i][j+(1<<k-1)][k-1]);
g[i][j][k]=min(g[i][j][k],g[i][j][k-1]);
}
}
}
}
int query(int x,int y,int goal)
{
long long tmp1=max(f[x][y][goal],f[x+n-(1<<goal)][y][goal]);
long long tmp2=max(f[x][y+n-(1<<goal)][goal],f[x+n-(1<<goal)][y+n-(1<<goal)][goal]);
long long tmp3=max(tmp1,tmp2);
long long tmp4=min(g[x][y][goal],g[x+n-(1<<goal)][y][goal]);
long long tmp5=min(g[x][y+n-(1<<goal)][goal],g[x+n-(1<<goal)][y+n-(1<<goal)][goal]);
long long tmp6=min(tmp4,tmp5);
return tmp3-tmp6;
}
signed main()
{
scanf("%d%d%d",&a,&b,&n);
inc(i,1,a){
inc(j,1,b){
scanf("%d",&mmap[i][j]);
}
}
build();
int goal=log2(n);
int ans=INT_MAX;
inc(i,1,a-n+1){
inc(j,1,b-n+1){
ans=min(ans,query(i,j,goal));
}
}
cout<<ans;
}
在做一维和二维ST表的时候,我们可以自己推出:三维的ST表,甚至于四维的ST表;只不过由于他们的时间复杂度较高,内存需求较大,我们便不再需要他们了。但这种思维可以运用到别的地方。
区间最值的优秀数据结构---ST表的更多相关文章
- 数据结构-ST表
数据结构-ST表 不可修改,在线查询的 RMQ 问题. 其中 \(f[i][j]\) 表示 \(i\sim i+(1<<j)-1\) 这段的 RMQ 值. 时间复杂度 \(O(n\log ...
- 模板 - 数据结构 - ST表/SparseTable
SparseTable,俗称ST表,其功能,就是静态的RMQ(区间最值查询)问题的解决.注意传入查询的时候两个参数的合法性,或者可以进行一次全部初始化来使得越界值不产生负面影响.不过访问越界是写程序的 ...
- 模板 - 数据结构 - ST表 + 二维ST表
区间最大值,$O(nlogn)$ 预处理,$O(1)$ 查询,不能动态修改.在查询次数M显著大于元素数量N的时候看得出差距. 令 $f[i][j]$ 表示 $[i,i+2^j-1]$ 的最大值. 显然 ...
- ST表 求 RMQ(区间最值)
RMQ即Range Minimum/Maximun Query,中文意思:查询一个区间的最小值/最大值 比如有这样一个数组:A{3 2 4 5 6 8 1 2 9 7},然后问你若干问题: 数组A下标 ...
- st表、树状数组与线段树 笔记与思路整理
已更新(2/3):st表.树状数组 st表.树状数组与线段树是三种比较高级的数据结构,大多数操作时间复杂度为O(log n),用来处理一些RMQ问题或类似的数列区间处理问题. 一.ST表(Sparse ...
- ST表学习笔记
ST表是一种利用DP思想求解最值的倍增算法 ST表常用于解决RMQ问题,即求解区间最值问题 接下来以求最大值为例分步讲解一下ST表的建立过程: 1.定义 f[i][j]表示[i,i+2j-1]这个长度 ...
- [Bzoj4540][Hnoi2016] 序列(莫队 + ST表 + 单调队列)
4540: [Hnoi2016]序列 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 1567 Solved: 718[Submit][Status] ...
- LOJ2014 SCOI2016 萌萌哒 并查集、ST表优化连边
传送门 一个朴素的做法就是暴力连边并查集,可是这是\(O(n^2)\)的.发现每一次连边可以看成两个区间覆盖,这两个区间之间一一对应地连边.可线段树对应的两个节点的size可能不同,这会导致" ...
- bzoj3277 串 (后缀数组+二分答案+ST表)
常见操作:先把所有串都连到一起,但中间加上一个特殊的符号(不能在原串中/出现过)作为分割 由于全部的子串就等于所有后缀的所有前缀,那我们对于每一个后缀,去求一个最长的前缀,来满足这个前缀在至少K个原串 ...
随机推荐
- Ubuntu安装jdk10
一:去官网下载jdk,和jre 因为jdk10之后jdk和jre是分开的 jdk下载 jre下载 二:解压缩,并放到指定目录 # 创建目录 sudo mkdir /usr/lib/java ...
- sh_20_for语法演练
sh_20_for语法演练 for num in [1, 2, 3]: print(num) if num == 2: break else: # 如果循环体内部使用break退出了循环 # else ...
- Lock和synchronized的区别
总结来说,Lock和synchronized有以下几点不同: 1)Lock是一个接口,而synchronized是Java中的关键字,synchronized是内置的语言实现: 2)synchroni ...
- Spring Boot教程(三十四)使用Redis数据库(2)
除了String类型,实战中我们还经常会在Redis中存储对象,这时候我们就会想是否可以使用类似RedisTemplate<String, User>来初始化并进行操作.但是Spring ...
- Ranger使用solrCloud存储审计日志
Ranger使用solrCloud存储审计日志 标签(空格分隔): Ranger 1, Zookeeper 搭建 1,忽略.默认已经搭建好zk 集群. VECS17820:2181,VECS17821 ...
- [CSP-S模拟测试]:那一天我们许下约定(DP+组合数学)
题目传送门(内部题2) 输入格式 每个测试点有多组测试数据.对于每组数据,有一行共三个整数$N$,$D$,$M$含义如题.输入结束标识为$“0 0 0”$ (不含引号). 输出格式 对于每组数据,输出 ...
- linux开机执行脚本
有些服务用命令启动的想要做到开机启动可以 /etc/profile.d/ 下面建一个脚本文件(这个目录优先级最低) #!/bin/bash ... 转载请注明博客出处:http://www.cnblo ...
- uni-app 尺寸单位
uni-app 支持的通用 css 单位包括 px.rpx px 即屏幕像素 rpx 即响应式px,一种根据屏幕宽度自适应的动态单位.以750宽的屏幕为基准,750rpx恰好为屏幕宽度.屏幕变宽,rp ...
- koa 基础(八)koa 中间件的执行顺序
1.koa 中间件的执行顺序 app.js /** * koa 中间件的执行顺序 */ // 引入模块 const Koa = require('koa'); const router = requi ...
- Druid连接池(无框架)
关于连接池有不少技术可以用,例如c3p0,druid等等,因为druid有监控平台,性能在同类产品中算top0的.所以我采用的事druid连接池. 首先熟悉一个技术,我们要搞明白,为什么要用他, 他能 ...