倍增——ST表
ST表——解决区间最值问题的有力工具,以倍增为思想,可以在O(nlogn)的时间内进行预处理,以O(1)的时间进行查询
以数组Max[i][j]表示从 i 位置开始,向后 2j 个数中的最大值为多少
转移时,将一段区间一分为二,再分别取区间最大值
查询时,计算出 log2(查询区间长度),以此为Max数组的第二位,然后分别对左右端点进行查询
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<math.h> 5 #include<algorithm> 6 #define ll long long 7 using namespace std; 8 9 ll n,m,p,q; 10 ll const s=1e5+10; 11 ll maxn[s][100]; 12 13 inline ll read()//快读 14 { 15 ll x=0,f=1;char ch=getchar(); 16 while (!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();} 17 while (isdigit(ch)){x=x*10+ch-48;ch=getchar();} 18 return x*f; 19 } 20 21 ll find(ll L,ll R)//进行区间查询 22 { 23 ll k=log2(R-L+1); 24 return max(maxn[L][k],maxn[R-(1<<k)+1][k]);//以左端点向右 2^k,和以右端点向左 2^k 个单位进行查询,一定可以覆盖到从 L 到 R 的最大值 25 } 26 27 int main(void) 28 { 29 scanf("%lld%lld",&n,&m); 30 31 for(int i=1;i<=n;i++) 32 { 33 maxn[i][0]=read(); 34 } 35 for(int j=1;j<=21;j++)//预处理 36 { 37 for(int i=1;i+(1<<j)-1<=n;i++) 38 { 39 maxn[i][j]=max(maxn[i][j-1],maxn[i+(1<<(j-1))][j-1]); 40 } 41 } 42 43 for(int i=1;i<=m;i++) 44 { 45 p=read(); 46 q=read(); 47 printf("%lld\n",find(p,q)); 48 } 49 50 return 0; 51 }