一、ST算法

ST算法(Sparse Table Algorithm)是用于解决RMQ问题(区间最值问题,即Range Maximum/Minimum Question)的一种著名算法。

ST算法能在复杂度为\(O(NlogN)\)的预处理后,以\(O(1)\)的复杂度在线处理序列区间内的最大值/最小值。

值得注意的是,ST算法并不能处理需要修改点权的区间最值问题。

  • ST表的实现同样依据倍增思想,设\(f(i,j)\)表示序列下标区间为\([i,i+2^{j}-1]\)的最值,即从\(i\)在内的\(2^j\)个数的最大值。

    递推过程中的转移方程与LCA的思想类似,新的区间最值由原区间翻倍推出,转移方程为:

\[f[i,j]=max(f[i,j-1],f[i+2^{j-1},j-1])
\]

\[f[i,j]=min(f[i,j-1],f[i+2^{j-1},j-1])
\]

图示(很良心):

  • 当我们询问任意区间[l,r]的最大/最小值的时候,我们计算出一个\(k\),使得\(2^k \lt r-l+1\leq 2^{k+1}\),这样保证我们的覆盖长度\(2^k\)是区间能覆盖最大的长度。此时询问两个区间\([l,r]\),\([r-2^{k}+1,r]\)的极值就能求出该区间的最大/最小值,尽管区间可能重叠,由于我们求的是最大/最小值,因此重叠区间对答案没有影响。

    图示(查询[3,23]区间最值):


二、ST算法の具体实现

1. 初始化

for(int i=1;i<=n;i++){
scanf("%d",a[i]);
f[i][0]=a[i];//[i,i]的最值就是a[i]
}

2. 求出ST表

int maxn=log(n)/log(2)+1;
for(int j=1;j<maxn;j++)
for(int i=1;i<=n-(1<<j)+1;i++)
f[i][j]=max(f[i][j-1],f[i+(1<<j-1)][j-1]);

3. 询问

询问[l,r]的最大值,ans为答案。

int k=log(r-l+1)/log(2);
int ans=max(f[l][k],f[r-(1<<k)+1][k]);

附:log(n)函数求出的值是\(lgn\),为了求出\(log_2n\),我们可以使用换底公式:\(log_2n=\frac{lgn}{lg2}\)解决,时间复杂度为\(O(1)\)。

除此之外,如果有同学认为\(log()\)常数大,我们同样可以手动求出\(log_2n\)的值:

Log[0]=-1;
for(int i=1;i<=n;i++) Log[i]=Log[i>>1]+1;

三、例题

例1:P3865 【模板】ST表

Code:

#include<bits/stdc++.h>
const int logN=25;
const int N=1e7;
using namespace std;
int a[N],f[N][logN];
int m,n,x,y;
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
f[i][0]=a[i];
}
int maxn=log(n)/log(2)+1;
for(int j=1;j<maxn;j++)
for(int i=1;i+(1<<j)-1<=n;i++)
f[i][j]=max(f[i][j-1],f[i+(1<<j-1)][j-1]);
for(int i=1;i<=m;i++){
scanf("%d%d",&x,&y);
int k=log(y-x+1)/log(2);
printf("%d\n",max(f[x][k],f[y-(1<<k)+1][k]));
}
return 0;
}

例2:P2880 [USACO07JAN]平衡的阵容Balanced Lineup

分别预处理出最大值和最小值,询问时相减。

Code:

#include<bits/stdc++.h>
using namespace std;
int n,q,f[50010][25],g[50010][25],a[50010];
int main()
{
scanf("%d%d",&n,&q);
for(int i=1;i<=n;i++) scanf("%d",&a[i]),f[i][0]=g[i][0]=a[i];
int maxn=log(n)/log(2)+1;
for(int j=1;j<=maxn;j++)
for(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]);
}
for(int i=1,l,r;i<=q;i++){
scanf("%d%d",&l,&r);
int k=log(r-l+1)/log(2);
int ans=max(f[l][k],f[r-(1<<k)+1][k])-min(g[l][k],g[r-(1<<k)+1][k]);
printf("%d\n",ans);
}
return 0;
}

[总结]RMQ问题&ST算法的更多相关文章

  1. RMQ的ST算法

    ·RMQ的ST算法    状态设计:        F[i, j]表示从第i个数起连续2^j个数中的最大值    状态转移方程(二进制思想):        F[i, j]=max(F[i,j-1], ...

  2. RMQ(ST算法)

    RMQ(Range Minimum/Maximum Query),即区间最值查询,是指这样一个问题:对于长度为n的数列a,回答若干询问RMQ(A,i,j)(i, j<=n),返回数列a中下标在i ...

  3. RMQ之ST算法模板

    #include<stdio.h> #include<string.h> #include<iostream> using namespace std; ; ],M ...

  4. RMQ问题+ST算法

    一.相关定义 RMQ问题 求给定区间的最值: 一般题目给定许多询问区间. 常见问题:对于长度为n的数列A,回答若干询问RMQ(A,i,j)(i,j<=n),返回数列A中下标在i,j之间的最小/大 ...

  5. RMQ问题——ST算法

    比赛当中,常会出现RMQ问题,即求区间最大(小)值.我们该怎样解决呢? 主要方法有线段树.ST.树状数组.splay. 例题 题目描述 2008年9月25日21点10分,酒泉卫星发射中心指控大厅里,随 ...

  6. RMQ问题ST算法 (还需要进一步完善)

    /* RMQ(Range Minimum/Maximum Query)问题: RMQ问题是求给定区间中的最值问题.当然,最简单的算法是O(n)的,但是对于查询次数很多(设置多大100万次),O(n)的 ...

  7. RMQ 问题 ST 算法(模板)

    解决区间查询最大值最小值的问题 用 $O(N * logN)$ 的复杂度预处理 查询的时候只要 $O(1)$ 的时间  这个算法是 real 小清新了   有一个长度为 N 的数组进行 M 次查询 可 ...

  8. RMQ之ST算法

    #include <stdio.h> #include <string.h> ; int a[N]; ]; inline int min(const int &a, c ...

  9. Round #4 RMQ问题ST算法

    前几天群里看到有人问[JSOI2008]最大数,一道很简单的问题,线段树无脑做,但是看到了动态ST,emmm,学学吧,听大佬说了下思路,还好,不难的: 四道题都可以用其他数据结构或做法代替,例如线段树 ...

随机推荐

  1. 升级Kubernetes 1.18前,你不得不知的9件事

    本文来自Rancher Labs 昨天Kubernetes最新版本v1.18已经发布,其包含了38项功能增强,其中15项为稳定版功能.11项beta版功能以及12项alpha版功能.在本文中,我们将探 ...

  2. beautifulsoup实现文章截取和脚本攻击

    引子:现在我们所写的所有高大上,炫酷的网页,在数据库中是如何存储的呢?其实数据库中存储的所有高大上的文章都是存的html,然后我们平时看的写的都是由于编辑器的原因,在编辑器内部做了转换,所以我们可以直 ...

  3. Trie树-XOR-1695. Kanade的三重奏

    2020-03-18 21:58:18 问题描述: 给你一个数组A [1..n],你需要计算多少三元组(i,j,k)满足(i <j <k)和((A [i] xor A [j])<(A ...

  4. linux golden-dict个性化添加词典

    国内有道,百度等参考https://www.jianshu.com/p/9bf577335945如果和我一样,想要添加大名鼎鼎的韦氏词典英文词典,则地址如下https://www.merriam-we ...

  5. Android LinearLayout线性布局详解

    为了更好地管理Android应用的用户界面里的各组件,Android提供了布局管理器.通过使用布局管理器,Android应用图形用户界面具有良好的平台无关性.推荐使用布局管理器来管理组件的分布.大小, ...

  6. promise的优势

    通过不同的方式读取在 files 文件夹下的三个文件来引出 promise 在处理异步时与回调函数相比的优势,files 文件夹有三个文件 a.json,b.json,c.json. // a.jso ...

  7. c++中的多态机制

    目录 1  背景介绍 2  多态介绍 2-1  什么是多态 2-2  多态的分类 2-3  动态多态成立的条件 2-4  静态联编和动态联编 2-5  动态多态的实现原理    2-6   虚析构函数 ...

  8. .Net平台技术栈?不止于此

    首先援引一名工友几年前的文章:http://csharper.blog.51cto.com/3052247/1330022,结合当前微软技术领域及平台工具现状,文章有增改. .NET是个很大.很宽.很 ...

  9. python ——钟表

    1.表盘 from turtle import * from datetime import * def Skip(step):#表盘不连续地画图 penup() forward(step) pend ...

  10. ThreadPoolExcutor 原理探究

    概论 线程池(英语:thread pool):一种线程使用模式.线程过多会带来调度开销,进而影响缓存局部性和整体性能.而线程池维护着多个线程,等待着监督管理者分配可并发执行的任务.这避免了在处理短时间 ...