Title

(模板)st表

【模板】ST 表 && RMQ 问题

题目描述

给定一个长度为 \(N\) 的数列,和 $ M $ 次询问,求出每一次询问的区间内数字的最大值。

输入格式

第一行包含两个整数 \(N,M\),分别表示数列的长度和询问的个数。

第二行包含 \(N\) 个整数(记为 \(a_i\)),依次表示数列的第 \(i\) 项。

接下来 \(M\) 行,每行包含两个整数 \(l_i,r_i\),表示查询的区间为 \([l_i,r_i]\)

输出格式

输出包含 \(M\) 行,每行一个整数,依次表示每一次询问的结果。

提示

对于 \(30\%\) 的数据,满足 \(1\le N,M\le 10\)

对于 \(70\%\) 的数据,满足 \(1\le N,M\le {10}^5\)

对于 \(100\%\) 的数据,满足 \(1\le N\le {10}^5\)\(1\le M\le 2\times{10}^6\)\(a_i\in[0,{10}^9]\)\(1\le l_i\le r_i\le N\)

代码

#include <bits/stdc++.h>
const int maxn = 1e5;
inline int read()
{
    int x = 0, flag = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9')
    {
        if(ch == '-')
        {
            flag = -1;
        }
        ch = getchar();
    }
    while(ch <= '9' && ch >= '0')
    {
        x = x * 10 + ch - '0';
        ch = getchar();
    }
    return x * flag;
}

int nums[maxn];
int ans[maxn][32];
// ans[i][j] 从i开始长度为2^j的数据的最值 ,也就是区间[i, i + 2^j - 1]

void st(int n) // 预处理
{
    for (int i = 1; i <= n; i++)
    {
        ans[i][0] = nums[i];
    }
    int m = log2(n);
    // 注意这里要先枚举j
    for (int j = 1; j <= m; j++)
    {
        // i + 2 ^ j - 1 <= n --> i <= n + 1 - 2 ^ j
        int t = n + 1 - (1 << j);
        for (int i = 1; i <= t; i++)
        {
            ans[i][j] = std::max(ans[i][j - 1], ans[i + (1 << (j - 1))][j - 1]);
        }
    }   
}

int query(int l, int r)
{
    int t = log2(r - l + 1);
    // 因为任何一个数都能够拆分成二进制
    int res = std::max(ans[l][t], ans[r + 1 - (1 << t)][t]);
    return res;
}


signed main()
{
    int n = read(), m = read();
    for (int i = 1; i <= n; i++)
    {
        nums[i] = read();
    }
    int l = 0, r = 0;
    st(n);
    for (int i = 1; i <= m; i++)
    {
        l = read(), r = read();
        std::cout << query(l, r) << '\n';
    }
}
posted @ 2024-09-29 09:19  栗悟饭与龟功気波  阅读(25)  评论(0)    收藏  举报