题目背景
题目
这是一道ST表经典题——静态区间最大值
请注意最大数据时限只有0.8s,数据强度不低,请务必保证你的每次查询复杂度为 O(1)。若使用更高时间复杂度算法不保证能通过。
如果您认为您的代码时间复杂度正确但是 TLE,可以尝试使用快速读入:
inline int read()
{
int x=0,f=1;char ch=getchar();
while (!isdigit(ch)){
if (ch=='-') f=-1;ch=getchar();}
while (isdigit(ch)){
x=x*10+ch-48;ch=getchar();}
return x*f;
}
题目描述
给定一个长度为 N 的数列,和 M 次询问,求出每一次询问的区间内数字的最大值。
输入格式
第一行包含两个整数 N, M ,分别表示数列的长度和询问的个数。
第二行包含 N 个整数(记为 a i),依次表示数列的第 i 项。
接下来 M 行,每行包含两个整数 l i,r i ,表示查询的区间为 [l i,r i ]
输出格式
输出包含 M 行,每行一个整数,依次表示每一次询问的结果。
输入输出样例
输入 #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
分析:
此题为 S T ST ST表 (查询区间最值 R M Q RMQ RMQ)的模板题
你谷还贴心的在题面上附了一个快读模板 防止 T L E TLE TLE
对于区间 [ l , r ] [l,r] [l,r] 其长度设为 l e n len len 一定存在一个 2 k 2^k 2k 满足 l e n / 2 < = 2 k < l e n len/2<=2^k<len len/2<=2k<len 此时 [ l , r ] [l,r] [l,r]的最大值即为 m a x ( f [ l ] [ k ] , f [ r − 2 k + 1 ] [ k ] ) max(f[l][k],f[r-2^k+1][k]) max(f[l][k],f[r−2k+1][k])
设 a [ i ] [ j ] = i a[i][j]=i a[i][j]=i到 i + j i+j i+j之间的最大值 :
a [ i ] [ j ] = m a x ( a [ i ] [ j − 1 ] , a [ i + ( 1 < < ( j − 1 ) ) ] [ j − 1 ] ) a[i][j]=max(a[i][j-1],a[i+(1<<(j-1))][j-1]) a[i][j]=max(a[i][j−1],a[i+(1<<(j−1))][j−1])
当然 莫队永远滴神!!
CODE:
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
const int MAXN=1e6+10;
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;
}
int a[MAXN][21];
int ques(int l,int r)
{
int k=log2(r-l+1);
return max(a[l][k],a[r-(1<<k)+1][k]); //RMQ
}
int main()
{
int n=read(),m=read();
for(int i=1;i<=n;i++) a[i][0]=read();
for(int j=1;j<=21;j++)
for(int i=1;i+(1<<j)-1<=n;i++)
a[i][j]=max(a[i][j-1],a[i+(1<<(j-1))][j-1]); //计算最大值
for(int i=1;i<=m;i++)
{
int l=read(),r=read();
printf("%d\n",ques(l,r)); //查询最大值
}
return 0;
}