【洛谷 P3865】[模板]ST表【ST表&RMQ】

题目背景

题目
这是一道ST表经典题——静态区间最大值

请注意最大数据时限只有0.8s,数据强度不低,请务必保证你的每次查询复杂度为 O(1)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^klen/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[r2k+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][j1],a[i+(1<<(j1))][j1])
当然 莫队永远滴神!!

CODE:

#include
#include
#include
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;
}

你可能感兴趣的:(ST表,洛谷有题,RMQ)