题目背景
这是一道ST表经典题——静态区间最大值
请注意最大数据时限只有0.8s,数据强度不低,请务必保证你的每次查询复杂度为 O(1)
题目描述
给定一个长度为 N 的数列,和 M 次询问,求出每一次询问的区间内数字的最大值。
输入输出格式
输入格式:
第一行包含两个整数 N, M ,分别表示数列的长度和询问的个数。
第二行包含 N 个整数(记为 ai),依次表示数列的第 i 项。
接下来 M 行,每行包含两个整数 li, ri,表示查询的区间为 [ li, ri ]
输出格式:
输出包含 M 行,每行一个整数,依次表示每一次询问的结果。
输入输出样例
输出样例
9
9
7
7
9
8
7
9
讲解:
作用——O(nlogn)预处理,O(1) 求区间最大值
思想——倍增
设一个Max[ i ][ j ] 表示从 i 位置 ,长度2j 的区间最大值
以样例为例
9 3 1 7 5 6 0 8
Max[1][1]=9
Max[2][1]=3
Max[3][1]=7
Max[4][1]=7
Max[5][1]=6
Max[6][1]=6
Max[7][1]=8
Max[1][2]=9
Max[2][2]=7
Max[3][2]=7
Max[4][2]=7
Max[5][2]=8
Max[1][3]=9
查询(如图)
算出 k=log2(区间长度) ,等同于:
for(k=0;(1<<k)<=r-l+1;k++) ;
k--;
就好啦,很简单吧~个鬼
std代码
#include<cstdio> #include<cmath> #include<algorithm> using namespace std; const int MAXN=1e6+10; 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 Max[MAXN][21]; int Query(int l,int r) { int k=log2(r-l+1); return max(Max[l][k],Max[r-(1<<k)+1][k]); } int main() { int N=read(),M=read(); for(int i=1;i<=N;i++) Max[i][0]=read(); for(int j=1;j<=21;j++) for(int i=1;i+(1<<j)-1<=N;i++) { Max[i][j]=max(Max[i][j-1],Max[i+(1<<(j-1))][j-1]); // printf("Max[%d][%d]=%d ",i,j,Max[i][j]); } for(int i=1;i<=M;i++) { int l=read(),r=read(); printf("%d ",Query(l,r)); } return 0; }