ST表

非常小巧好用的数据结构,在处理静态的RMQ非常有力

思想

思想就是伟大的 倍增思想, O ( n l o g n ) O(nlogn) O(nlogn)的预处理 O ( 1 ) O(1) O(1)的查询。

预处理

设数组 m a x x [ i ] [ j ] maxx[i][j] maxx[i][j]为从i开始长度为 2 j 2^j 2j的区间内的最大值
那么 m a x x [ i ] [ j ] = m a x ( m a x x [ i ] [ j − 1 ] , m a x x [ i + 2 j − 1 ] [ j − 1 ] ) maxx[i][j] = max(maxx[i][j - 1], maxx[i + 2^{j - 1}][j-1]) maxx[i][j]=max(maxx[i][j1],maxx[i+2j1][j1])
很明显就可以发现只要处理了 2 j − 1 2^{j -1} 2j1这一层,就可以O(n)推出 2 j 2^{j} 2j这一层,一共倍增 l o g n logn logn次所以复杂度是 O ( n l o g n ) O(nlogn) O(nlogn)

查询

假设要查询[l,r]的最大值,设 k = i n t ( l o g 2 ( r − l + 1 ) ) k = int(log_2(r - l+ 1)) k=int(log2(rl+1))那么可以直接求出区间 [ l , l + 2 k − 1 ] 的 最 大 值 [l, l + 2^{k} - 1]的最大值 [l,l+2k1],同理也可以求出 [ r − 2 k + 1 , r ] [r - 2^{k} + 1,r] [r2k+1,r]的最大值,而这两个区间一定覆盖了[l,r]的所有值,所以[l,r]的最大值就是 m a x ( m a x x [ i ] [ k ] , m a x x [ i − ( 1 < < k ) + 1 ] [ k ] ) max(maxx[i][k], maxx[i - (1 << k) + 1][k]) max(maxx[i][k],maxx[i(1<<k)+1][k])

代码

题目

#include<bits/stdc++.h>
#define ll long long
#define INF 0x3f3f3f3f
#define eps 1e-8
#define endl '\n'
using namespace std;
const ll maxn = 1e6 + 5;
const ll mod = 1e9 + 7;
int n,m, maxx[maxn][22];

inline int read(){
    char c=getchar();int x=0,f=1;
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
    return x*f;
}

void build(){
    for(int j = 1; j <= 21; j++)
        for(int i = 1; i + (1 << j) - 1 <= n; i++)
            maxx[i][j] = max(maxx[i][j - 1], maxx[i + (1 << (j - 1))][j - 1]);
}

int query(int l, int r){
    int k = log2(r - l + 1);
    return max(maxx[l][k], maxx[r - (1 << k) + 1][k]);
}

int main(){
    scanf("%d %d",&n,&m);
    for(int i = 1; i <= n; i++)maxx[i][0] = read();
    build();
    int l,r;
    while(m--){
        scanf("%d %d", &l, &r);
        printf("%d\n", query(l,r));
    }
    return 0;
}
©️2020 CSDN 皮肤主题: 深蓝海洋 设计师:CSDN官方博客 返回首页