原题网址:P3865 【模板】ST 表 + 快速读取
题目背景 这是一道 ST 表经典题——静态区间最大值请注意最大数据时限只有 0.8s,数据强度不低,请务必保证你的每次查询复杂度为O(1)O(1)。若使用更高时间复杂度算法不保证能通过。题目描述 给定一个长度为 NN 的数列,和 MM
次询问,求出每一次询问的区间内数字的最大值。输入格式 第一行包含两个整数 N,MN,M,分别表示数列的长度和询问的个数。
第二行包含 NN 个整数(记为 a_ia i ),依次表示数列的第 ii 项。
接下来 MM 行,每行包含两个整数 l_i,r_il i ,r i ,表示查询的区间为 [l_i,r_i][l i
,r i ]。输出格式 输出包含 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
这个题就是ST模板题, 但是要用快速读取才能过, cin cout 关流都不行, scanf(),也不行
超时题解:
/*
https://www.luogu.com.cn/problem/P3865
P3865 【模板】ST 表
*/
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 10;
int f[maxn][20];
int n, m;
void ST() {
for(int j = 1; (1<<j) <= n; 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]);
}
}
}
int RMQ(int l, int r) {
int k = log2(r-l+1);
return max(f[l][k], f[r-(1<<k)+1][k]);
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin >> n >> m;
for(int i = 1; i <= n; i ++) {
cin >> f[i][0];
}
ST();
while(m --) {
int a, b;
cin >> a >> b;
cout << RMQ(a, b) << endl;
}
return 0;
}
快速读取:
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;
}
inline C++命名防止频繁调用,浪费空间
正确题解:
/*
https://www.luogu.com.cn/problem/P3865
P3865 【模板】ST 表
*/
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 10;
int f[maxn][20];
int n, m;
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 ST() {
for(int j = 1; (1<<j) <= n; 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]);
}
}
}
int RMQ(int l, int r) {
int k = log2(r-l+1);
return max(f[l][k], f[r-(1<<k)+1][k]);
}
int main() {
n = read(), m = read();
for(int i = 1; i <= n; i ++) {
f[i][0] = read();
}
ST();
while(m --) {
int a, b;
a = read(), b = read();
printf("%d\n", RMQ(a, b));
}
return 0;
}