题目背景
这是一道ST表经典题——静态区间最大值
请注意最大数据时限只有0.8s,数据强度不低,请务必保证你的每次查询复杂度为 O(1)O(1)
题目描述
给定一个长度为 NN 的数列,和 MM 次询问,求出每一次询问的区间内数字的最大值。
输入格式
第一行包含两个整数 N,MN,M ,分别表示数列的长度和询问的个数。
第二行包含 NN 个整数(记为 aiai),依次表示数列的第 ii 项。
接下来 MM行,每行包含两个整数 li,rili,ri,表示查询的区间为 [li,ri][li,ri]
输出格式
输出包含 MM行,每行一个整数,依次表示每一次询问的结果。
输入输出样例
输入 #1复制
8 8
9 3 1 7 5 6 0 8
1 6
1 5
2 7
2 6
1 8
4 8
3 7
1 8
输出 #1复制
9
9
7
7
9
8
7
9
说明/提示
对于30%的数据,满足: 1≤N,M≤101≤N,M≤10
对于70%的数据,满足: 1≤N,M≤1051≤N,M≤105
对于100%的数据,满足: 1≤N≤105,1≤M≤106,ai∈[0,109],1≤li≤ri≤N1≤N≤105,1≤M≤106,ai∈[0,109],1≤li≤ri≤N
题解
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e5 + 10;
const int logn = 20;
int Log[maxn], f[maxn][logn];
inline const int read()
{
int x = 0, f = 1; char ch = getchar();
while (ch < '0' || ch > '9') { if (ch == '-') f = -1; ch = getchar(); }
while (ch >= '0' && ch <= '9') { x = (x << 3) + (x << 1) + ch - '0'; ch = getchar(); }
return x * f;
}
void init()
{
Log[1] = 0; Log[2] = 1;
for (int i = 3; i < maxn; i++) Log[i] = Log[i / 2] + 1;
}
int main()
{
int n = read(), m = read();
for (int i = 1; i <= n; i++) f[i][0] = read();
init();
for (int j = 1; j <= logn; j++)
for (int i = 1; i + (1 << j) - 1 <= n; i++)
f[i][j] = max(f[i][j - 1], f[i + (1 << (j - 1))][j - 1]);
while (m--)
{
int l = read(), r = read();
int s = Log[r - l + 1];
printf("%d\n", max(f[l][s], f[r - (1 << s) + 1][s]));
}
return 0;
}