其他分享
首页 > 其他分享> > 数据结构 _ ST表 | RMQ 问题

数据结构 _ ST表 | RMQ 问题

作者:互联网

基本概念

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

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

实现

复杂度:
预处理:\(O(n \log n)\)
每次查询:\(O(1)\)

预处理

预处理复杂度: \(O(n \log n)\)

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

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

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

很明显\(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 [ l , l + 2 ^s − 1 ]\) 和 \(f [ r − 2^s + 1 , r ]\) 。其中\(s=log_2(r-l+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;
}

标签:RMQ,return,log,get,int,ST,include,数据结构
来源: https://www.cnblogs.com/kingwz/p/16512540.html