倍增——ST表

#洛谷P3865

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 }

 

posted @ 2020-07-05 15:13  雾隐  阅读(198)  评论(0编辑  收藏  举报