RMQ演算法 (ST演算法)

來源:互聯網
上載者:User

標籤:位操作   很多   printf   線上   art   偶數   can   get   查詢   

 概述:

  RMQ(Range Minimum/Maximum Query),即區間最值查詢,是指這樣一個問題:對於長度為n的數列A,回答若干詢問RMQ(A,i,j)(i,j<=n),返回數列A中下標在i,j之間的最小/大值。對於一次查詢,可以暴力地O(n),但是當查詢次數很多的時候,這樣的暴力就無法進行了。這時我們可以通過RMQ演算法來解決這個問題。

RMQ(ST):(關於學習RMQ的部落格:架構即講解比較詳細 , 具體代碼比較好)

  ST(Sparse Table)演算法是一個非常有名的線上處理RMQ問題的演算法,它可以在O(nlogn)時間內進行預先處理,然後在O(1)時間內回答每個查詢。

  首先是預先處理,用動態規劃(DP)解決。設A[i]是要求區間最值的數列,F[i, j]表示從第i個數起連續2^j個數中的最大值。例如數列3 2 4 5 6 8 1 2 9 7,F[1,0]表示第1個數起,長度為2^0=1的最大值,其實就是3這個數。 F[1,2]=5,F[1,3]=8,F[2,0]=2,F[2,1]=4……從這裡可以看出F[i,0]其實就等於A[i]。這樣,DP的狀態、初值都已經有了,剩下的就是狀態轉移方程。我們把F[i,j]平均分成兩段(因為f[i,j]一定是偶數個數字),從i到i+2^(j-1)-1為一段,i+2^(j-1)到i+2^j-1為一段(長度都為2^(j-1))。用上例說明,當i=1,j=3時就是3,2,4,5 和 6,8,1,2這兩段。F[i,j]就是這兩段的最大值中的最大值。於是我們得到了動態規劃方程F[i, j]=max(F[i,j-1], F[i + 2^(j-1),j-1])。

然後是查詢。取k=[log2(j-i+1)],則有:RMQ(A, i, j)=min{F[i,k],F[j-2^k+1,k]}。 舉例說明,要求區間[2,8]的最大值,就要把它分成[2,5]和[5,8]兩個區間,因為這兩個區間的最大值我們可以直接由f[2,2]和f[5,2]得到。

void ST(int N){    for(int i=1;i<=N;i++) dp[i][0] = vec[i];    for(int j=1;(1<<j) <= N;j++)    {        for(int i=1;i+(1<<j)-1<=N;i++)        {            dp1[i][j] = max(dp[i][j-1],dp[i+(1<<j-1)][j-1]); //由於移位操作的優先度低,1<<j-1 = 1<<(j-1);        }    }}int RMQ(int l,int r){    int k = 0;    while((1<<k+1) <= r-l+1) k++;    return max(dp1[l][k],dp1[r-(1<<k)+1][k]);}

 

POJ-2364

 1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 using namespace std; 5 const int MAX_N = 5e4+9; 6 const int INF = 1e9+7; 7 int vec[MAX_N]; 8 int dp1[MAX_N][25]; 9 int dp2[MAX_N][25];10 void ST(int N)11 {12     for(int i=1;i<=N;i++) dp1[i][0] = dp2[i][0] = vec[i];13     for(int j=1;(1<<j)<=N;j++)14     {15         for(int i=1;i+(1<<j)-1 <= N;i++)16         {17             dp1[i][j] = max(dp1[i][j-1],dp1[i+(1<<j-1)][j-1]);18             dp2[i][j] = min(dp2[i][j-1],dp2[i+(1<<j-1)][j-1]);19         }20     }21 }22 int RMQ(int l,int r)23 {24     int k = 0;25     while((1<<k+1) <= r-l+1) k++;26     return max(dp1[l][k],dp1[r-(1<<k)+1][k]) - min(dp2[l][k],dp2[r-(1<<k)+1][k]);27 }28 int main()29 {30     int N,M,T;31     while(cin>>N>>M)32     {33         for(int i=1;i<=N;i++)34         {35             scanf("%d",&vec[i]);36         }37         ST(N);38         for(int i=0;i<M;i++)39         {40             int l,r;41             scanf("%d%d",&l,&r);42             int ans = RMQ(l,r);43             printf("%d\n",ans);44         }45     }46     return 0;47 }
View Code

RMQ演算法 (ST演算法)

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.