倍增算法1

首先用倍增法解决一道求区间最大值问题,算是倍增的入门了。

其实也算是一种dp,不过大家把这个二维dp数组叫做ST表。

ST表数组:f[i][j],表示区间【i,i+2j-1】的最大值。这个区间的大小是2j个数。

ST表的初始化:f[i][0]=a[i]。(显然这是区间大小为1的时候)

ST表的递推过程:

1,由区间大小为1的项转移得到区间大小为21的项

2,由区间为21的项转移得到区间为22的项

3,由区间为22的项转移得到区间为23的项

。。。

这就是倍增的由来了吧。

这个递推过程的代码:

1 void RMQ(int N){
2     for(int j=1;(1<<j)<=N;j++)    
3     for(int i=1;i<=N;i++)
4         if(i+(1<<j)-1<=N)
5          f[i][j]=max(f[i][j-1],f[i+(1<<(j-1))][j-1]); 
6 }

经过处理后,访问一段长区间便能利用事先处理好的数据得出答案

比如询问最大值的一项处理技术:

因为区间的长度为j-i+1,所以可以取k=log2(j-i+1)。

则RMQ(A,i,j)=max(f[i][k],f[j-2^k+1][k])。

 1 #include<algorithm>
 2 #include<iostream>
 3 #include<cstring>
 4 #include<cstdio>
 5 #include<cmath>
 6 using namespace std;
 7 int a[100001],f[100001][20];
 8 
 9 void RMQ(int N){
10     for(int j=1;(1<<j)<=N;j++)    
11     for(int i=1;i<=N;i++)
12         if(i+(1<<j)-1<=N)
13          f[i][j]=max(f[i][j-1],f[i+(1<<(j-1))][j-1]); 
14 }
15 int main(){
16     int N,M;
17     int tt;
18     cin>>tt;
19     while(tt--) 
20     {
21         cin>>N;
22     for(int i=1;i<=N;i++) cin>>a[i];
23     for(int i=1;i<=N;i++) f[i][0]=a[i];
24     RMQ(N); 
25     cin>>M;
26     while(M--){
27         int l,r;
28         cin>>l>>r;
29          int k=(int)(log((double)(r-l+1))/log(2.0)); 
30         printf("%d
",max(f[l][k],f[r-(1<<k)+1][k]));
31     }
32     }
33     return 0;
34 }
原文地址:https://www.cnblogs.com/lnu161403214/p/9255533.html