淺談RMQ

RMQ是英文Range Maximum(Minimum) Query的縮寫,顧名思義是用來求某個區間內的最大值或最小值,通常用在要多次詢問一些區間的最值的問題中。
RMQ的原理實際上是動態規劃,我們用A[1…N]表示一組數,用[Li,Ri]表示題目中所涉及到詢問區間。設F[I,J]表示從A[I]到A[I+2j2^{j}-1]這個範圍內的最大值,也就是以A[I]爲起點連續2j2^{j}個數的最大值,由於元素個數爲2j2^{j}個,所以從中間平均分成兩部分,每一部分的元素個數剛好爲2j12^{j-1}個.
整個區間的最大值一定是左右兩部分最大值的較大值,滿足動態規劃的最優化原理,分析得到狀態轉移方程:F[I,J]=max(F[I,J-1],F[I+2j2^{j}-1,J-1]),邊界條件爲F[I,0]=A[I],這樣就可以在O(NlgN)的時間複雜度內預處理F數組。

例題:
【飛船】
(airship.pas)
【題目描述】
2008年9月25日21點10分,酒泉衛星發射中心指控大廳裏,隨着指揮員一聲令下,長征二號F型火箭在夜空下點火起飛,神舟七號飛船載着翟志剛、劉伯明、景海鵬3位航天員,在戈壁茫茫的深邃夜空中飛向太空,開始人類漫步太空之旅。第583秒,火箭以7.5公里/秒的速度,將飛船送到近地點200公里、遠地點350公里的橢圓軌道入口。而此時,火箭的燃料也消耗殆盡,即將以悲壯的方式與飛船告別。這個過程,在短短不到10分鐘時間內,翟志剛和他的兩名戰友體會到了從超重到失重的過程。
除了超重和失重的感覺之外,就是浩瀚的長空中璀璨的星星,和地面上看到的星星不同,在太空中看到的星星是成一條直線的,一共有N(1<=N<=100,000)顆星星,編號爲1到N,每個星星有自己的體積,由於在飛船中很無聊,除了不停地玩弄手中失重的書和筆之外沒有別的事可幹,此時翟志剛說我們來玩遊戲吧,一共玩了M輪(1<=M<=100,000),每一輪都是給出兩個整數L和R(1<=L<=R<=N),詢問第L到第R顆星星之間最大星星的體積,每次答對的人就可以多休息一段時間。
由於翟志剛還要進行太空漫步,所以他現在請你幫忙,你得到的回報就是太空餅乾。
【輸入格式】
第一行輸入N,M
接下來一行N個整數,表示星星的體積(1<=體積<=maxlongint)
接下來M行,每行兩個整數L_i,R_i,表示詢問區間。
【輸出格式】
輸出M行,每一行表示詢問區間L_i到R_i之間最大星星的體積。
【樣例輸入】
6 3
5 7 3 9 2 10
1 3
2 4
3 6
【樣例輸出】
7
9
10
【數據說明】
50%的數據滿足1<=N,M<=5000
##標程:

uses math;
var
        f:array[0..200000,0..18]of int64;
        a:array[0..200000]of int64;
        i,j,n,m,x,y,k,s:longint;
begin
        readln(n,m);
        for i:=1 to n do
        begin
                read(a[i]);
                f[i,0]:=a[i];
        end;
        for j:=1 to trunc(ln(n)/ln(2)) do //ln(n)/ln(2)表示2的ln(n)/ln(2)次方等於n
                for i:=1 to n-(1 shl j)+1 do
                        f[i,j]:=max(f[i,j-1],f[i+(1 shl (j-1)),j-1]);//(1 shl (j-1))表示2的j-1次方
        for i:=1 to m do
        begin
                readln(x,y);
                k:=trunc(ln(y-x+1)/ln(2));
                writeln(max(f[x,k],f[y-(1 shl k)+1,k]));
        end;
end.
發佈了128 篇原創文章 · 獲贊 76 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章