ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

数据结构 _ ST表 | RMQ 问题

2022-07-23 19:34:37  阅读:128  来源: 互联网

标签:RMQ return log get int ST include 数据结构


基本概念

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]\)平均分成两部分:

  • 左边:\([i,i+2^{j−1}−1]\)
  • 右边:\([i+2^{j−1},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

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有