HELLO WORLD--一起加油(🍺)!|

kingwzun

园龄:3年6个月粉丝:111关注:0

数据结构 _ ST表 | RMQ 问题

基本概念

RMQ问题
RMQ英文是Range Maximum(Minimum) Query,
翻译就是区间求最值的意思。

ST表(Sparse Table,稀疏表)
是一种简单的数据结构,基于 倍增 思想,主要用来解决RMQ问题。
不支持修改操作

实现

复杂度:
预处理:O(nlogn)
每次查询:O(1)

预处理

预处理复杂度: O(nlogn)

状态表示:
f[i][j]表示以 i 为左端点,长度为2j的区间最大值.

状态转移 :
当j为0
此时区间长度为1,区间最值就是其本身对应的数组中的数。
代码就是:f[i][j]=a[i]

当j不为0
此时就将区间[i,j]平均分成两部分:

  • 左边:[ii+2j11]
  • 右边:[i+2j1j]

很明显f[i][j]就是两部分取最大值。
image

代码就是: f[i][j]=max(f[i][j-1],f[i+(1<<j-1)][j-1])

代码:

void get_st(){
for(int j=0;(1<<j)<=n;j++){
for(int i=1;i+(1<<j)-1<=n; i++){
if(j==0) f[i][j]=w[i];
else
f[i][j]=max(f[i][j-1],f[i+(1<<j-1)][j-1]);
}
}
}

查询

每次查询复杂度: O(1)

对于每个询问的[L,R]我们把它分成两部分,f[ll+2s1]f[r2s+1r] 。其中s=log2(rl+1)
取两个区间的最大值即可

如图
image

代码:

int query(int l,int r){
int len=r-l+1;
int k=log(len)/log(2);
return max(f[l][k],f[r-(1<<k)+1][k]);
}

模板代码

int f[N][20];
int n;
int w[N];
void get_st(){
for(int j=0;(1<<j)<=n;j++){
for(int i=1;i+(1<<j)-1<=n; i++){
if(j==0) f[i][j]=w[i];
else
f[i][j]=max(f[i][j-1],f[i+(1<<j-1)][j-1]);
}
}
}
int query(int l,int r){
int len=r-l+1;
int k=log(len)/log(2);
return max(f[l][k],f[r-(1<<k)+1][k]);
}

习题

1273. 天才的记忆

模板题

代码:

#include <iostream>
#include <cstring>
#include <vector>
#include <bits/stdc++.h>
#define endl '\n'
//#pragma GCC optimize(3)
#define int long long
#define pii pair<int, int>
using namespace std;
const int N = 2e5+10;
int min(int a, int b)
{
if (a > b)
return b;
else
return a;
}
int max(int a,int b){
if(a>b) return a;
else return b;
}
int f[N][20];
int n;
int w[N];
void get_st(){
for(int j=0;(1<<j)<=n;j++){
for(int i=1;i+(1<<j)-1<=n; i++){
if(j==0) f[i][j]=w[i];
else
f[i][j]=max(f[i][j-1],f[i+(1<<j-1)][j-1]);
}
}
}
int query(int l,int r){
int len=r-l+1;
int k=log(len)/log(2);
return max(f[l][k],f[r-(1<<k)+1][k]);
}
void solve(){
cin>>n;
for(int i=1;i<=n;i++) cin>>w[i];
get_st();
// for(int i=1;i<=n;i++)
// for(int j=0;j<=2;j++)
// cout<< f[i][0]<<" ";
// cout<<endl;
int m;cin>>m;
while(m--){
int l,r;cin>>l>>r;
cout<<query(l,r)<<endl;
}
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
solve();
return 0;
}

本文作者:kingwzun

本文链接:https://www.cnblogs.com/kingwz/p/16512540.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   kingwzun  阅读(81)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起