ST表
ST表用来实现O(logn)预处理,O(1)查询区间最值。
不支持修改
适用于O(logn)查询区间最值会被卡的情况。
以查询最大值为例。
预处理:记(f_{i,k})表示从i开始(2^k)个数的最大值,则
(f_{i,k})=max((f_{i,k}),(f_{i+2^{k-1}}),k-1)。
查询:设查询区间[l,r],令p为满足(2^Pleq r-l+1)的最大值,则答案为
max((f_{l,p}),(f_{r-2^P+1}),p)。
用两个长度为(2^p)的区间去覆盖查询区间,由于查询区间的长度属于[(2^p,2^{p+1})),故一定能够完整覆盖
#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
const int maxn=1e6+10;
int m,n,l,r,k;
int a[maxn][21];
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;
}
int query(int l,int r)
{
int k=log2(r-l+1);
return max(a[l][k],a[r-(1<<k)+1][k]);
}
int main()
{
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++)
{
l=read(),r=read();
printf("%d
",query(l,r));
}
return 0;
}
题目推荐