倍增算法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\n",max(f[l][k],f[r-(1<<k)+1][k]));
31     }
32     }
33     return 0;
34 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM