RMQ 问题及 ST 表

RMQ(Range Minimum/Maximum Query)问题指的是一类对于给定序列,要求支持查询某区间内的最大、最小值的问题。很显然,如果暴力预处理的话复杂度为 \(O(n^2)\),而此类问题数据又往往很大,不仅会爆时间,数组也存不下。我们需要一种能够 \(O(n\log n)\) 甚至 \(O(n)\) 预处理的数据结构,这便是ST表。

ST表(Sparse Table,应译为S表)是一种可以以 \(O(n\log n)\) 的优秀复杂度预处理出静态区间上的最大、最小值的算法,其核心是倍增的思想。它使用 \(ST[i][j]\) 表示原数组中 \(i\rightarrow i+2^j-1\) 的区间的最值。那么在查询时,只用找出两点间的距离的最小2的整数幂,然后从区间起点与终点减去这个幂分别查找取最值即可,比如要查询 \(2\rightarrow 7\),就可以先查询 \(2\rightarrow 5\),再查询 \(4\rightarrow 7\),然后相比较即可。

ST表

题目 ST表模板 题目大意:求静态区间最大值。

代码

#include<bits/stdc++.h>
using namespace std;

int n, m;
int ST[1000005][25];

int Read()
{
    int x = 0, op = 1;
    char ch = getchar();

    while (!isdigit(ch)) {
        if (ch == '-') op = -1;
        ch = getchar();
    }

    while (isdigit(ch)) {
        x = (x << 3) + (x << 1) + (ch - '0');
        ch = getchar();
    }
    return x * op;
}

void Init()
{
    int MaxLength = log2(n);

    for (int j = 1; j <= MaxLength; j++)
        for (int i = 1; i + (1 << j) - 1 <= n; i++)
            ST[i][j] = max(ST[i][j - 1], ST[i + (1 << (j - 1))][j - 1]);
}

int Work(int l, int r)
{
    if (l > r) swap(l, r);

    int Length = log2(r - l + 1);
    return max(ST[l][Length], ST[r - (1 << Length) + 1][Length]);
}

int main()
{
    n = Read(), m = Read();
    for (int i = 1; i <= n; i++)
        ST[i][0] = Read();

    Init();

    for (int i = 1; i <= m; i++)
        printf("%d\n", Work(Read(), Read()));
    return 0;
}
posted @ 2019-11-10 15:40  whx1003  阅读(184)  评论(0编辑  收藏  举报