亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

區間第K大值與RMQ問題

系統 2302 0

?? ? ?這次我們討論一下有關區間中的值的問題。如果你只想看RMQ,請跳過下面這幾段,在第一段代碼的后面有詳細的講解。

?? ? ?在競賽中,我們經常遇到最值問題。但是出題者往往給我們出一些這樣的題目,讓我們找到第K優解,而不是最優,比如K小生成樹、K優背包等等。這篇文章主要介紹另一個“K問題“,區間第K大值。

?? ? ?區間第K大值的題意很明確,對于一個區間,找到其中第K大的一個數輸出。這個問題可以用O(n 2 )的算法枚舉,但是當區間很大的時候這種方法就會很費時。我們還可以將區間內的序列排序,直接輸出a[k+l-1](l是區間左端點)即可。

?? ? ?我們知道,快排的原理是找到一個標準點,然后進行交換、分組,直到它的左邊(以遞增為例)都比它小,右邊都比它大為止。但是結合這道題來說,每進行一遍分 ? ? ?組,第K大值就會確定的位于其中一組,或者就是那個標準點。然后我們只用將有第K大值的那個組再進行分組、查找(不是標準點),或者直接輸出標準點(正好是標準點)。這樣,我們就可以以少于1/2的操作找到我們想要的數。

?? ? ?對于多次詢問,我們要保留下原始序列,以免之后再尋找時出現錯誤。

?? ? ?給出一道比較水的題,大家可以試一下~

?

?

      
【題目描述】(rqnoj350)
給出一個長度為N的序列A1,A2,A3,...,AN,其中每項都是
小于10
^ 5的自然數。
現在有M個詢問,每個詢問都是Ai...Aj中第k小的數等
于多少。
數據范圍:
在60
% 的數據中, 1 ≤N≤ 1000 1 ≤M≤ 1000
在100
% 的數據中, 1 ≤N≤ 10000 , 1 ≤M≤ 2000

【輸入格式】
第一行兩個正整數N,M。
第二行N個數,表示序列A1,A2,...,AN。
緊著的M行,每行三個正整數i,j,k(k≤j
- i + 1 ),表示
詢問Ai...Aj中第k小的數等于多少。

【輸出格式】
共輸出M行,第i行輸出第i個詢問的答案。

【樣例輸入】
4 3
4 1 2 3
1 3 1
2 4 3
1 4 4

【樣例輸出】
1
3
4

?

?

?

?? ? ?分析就不用了,直接貼代碼吧~

?

?? ? ?參考代碼:

?

      
1 program knum;
2 var
3 a,t: array [ 1 .. 3000000 ] of longint;
4 n,k,i,m,l,r:longint;
5 function sort(l,r,k:longint):longint; // 改編的快排
6 var
7 i,j,x,y:longint;
8 begin
9 if l = r then exit(a[l]); // 兩指針可能重合。這條語句可以減少時間消耗
10 i: = l;
11 j: = r;
12 x: = a[(i + j) shr 1 ];
13 repeat
14 while a[i] < x do inc(i);
15 while a[j] > x do dec(j);
16 if i <= j then
17 begin
18 y: = a[i];
19 a[i]: = a[j];
20 a[j]: = y;
21 inc(i);
22 dec(j);
23 end ;
24 until i > j;
25 if (k >= i) then exit(sort(i,r,k)); //
26 if (k <= j) then exit(sort(l,j,k));
27 exit(x); // 如果是標準點就直接輸出
28 end ;
29 begin
30 readln(n,m);
31 for i: = 1 to n do
32 read(t[i]);
33 for i: = 1 to m do
34 begin
35 a: = t; // 保留原序列,對“鏡子“序列進行操作
36 readln(l,r,k);
37 writeln(sort(l,r,l + k - 1 )); //
38 end
39 end .
40 P.S.① a)因為k∈[l,r],所以不用判斷i是否小于r;
41 b)由于i > j,這條語句和以下兩條語句沒有交集。
42 ②一定是l + k - 1 ,因為是區間的第K小值,所以尋找k肯定不對。
?

?

?

?

?? ? ?當然,對于區間最值問題(RMQ),這種方法也能解決。為什么還要有求區間最值(RMQ)的偉大的ST算法呢?

?? ? ?有句頗有哲理的話說得好,存在即合理。師傅告訴我,上面改裝快排的時間效率是O(nm),所以當m很大時,這種方法就無法快速出解了。這時,強大的ST(Sparse Table)算法應運而生(為了劇情需要^_^)!ST算法可以在O(nlogn)的時間中構造一個強大的數組,然后只用O(1)的時間就能針對每次詢問找到解。

?? ? ?這個強大的數組的名字叫做f[i,j](好俗…),表示從區間的第i位開始,長度為2 i 的區間的最大值(姑且以求區間最大值為例)。這句話聽起來很玄乎,可是怎么構造這個數組呢?

?? ? ?我們先把f[i,0]賦成讀入的第i個數(也就是以i為起點,長度為2 0 =1的區間內的最值)。因為j表示長度為2 j ,所以我們可以把整個f[i,j]表示的區間劃分[i,j-1]和[i+2 (j-1) ,j-1]兩個區間,然后調用f中存儲的兩個區間中的最大值,取其中較大的那個就行!

?? ? ?有的人可能疑惑,f[i,j]劃分的兩個空間的最值是什么時候求出來的呢?別忘了我們的初始化。有了j=0時的最值,j=1時的最值就很好求了。顯然,j的最大值是trunc(log 2 n),這樣,我們只要讓j從1循環到trunc(log 2 n),把目的區間由小逐漸擴大,之后就能隨意地調用原來的解啦!整個過程循環完以后,任何一個長度為2 j 的區間的最值就全部求出來了。

?? ? ?長度為2 j 區間的最值是有了,但是如果詢問的區間的長度2 j 和2 j+1 之間呢?舉一個例子。假設原序列是4 2 8 6 1 7 3,求3到7這個區間的最大值。

區間第K大值與RMQ問題

?? ? ?尋找的時候就只用尋找圖中的兩個區間的最大值即可,這樣整個區間就都能夠被覆蓋,即使交集也不會影響結果。

?? ? ?另外一道比較水的題,大家也可以試試~

?

      
【題目描述】(tyvj p1038)
老管家是一個聰明能干的人。他為財主工作了整整10年,財主為了讓自已賬目更加清楚。要求管家每天
記k次賬, 管家聰明能干,因而管家總是讓財主十分滿意。但是由于一些人的挑撥,財主還是對管家產生
了懷疑。于是他決定 種特別的方法來判斷管家的忠誠,他把每次的賬目按1, 2 3 …編號,然后不定時的
問管家問題,問題是這樣的:在 a b號賬中最少的一筆是多少?為了讓管家沒時間作假他總是一次問多個問題。

【輸入格式】
輸入中第一行有兩個數m,n表示有m(m
<= 100000 )筆賬,n表示有n個問題,n <= 100000
第二行為m個數,分別是賬目的錢數
后面n行分別是n個問題,每行有2個數字說明開始結束的賬目編號。

【輸出格式】
輸出文件中為每個問題的答案。具體查看樣例。

【樣例輸入】
10 3
1 2 3 4 5 6 7 8 9 10
2 7
3 9
1 10

【樣例輸出】
2 3 1

?

?

?? ? ?參考代碼:

?

      
1 program ST;
2 var
3 f: array [ 0 .. 100000 , 0 .. 19 ] of longint; // j的最大值是trunc(log2n),計算器算一下
4 i,j,n,m,l,r:longint;
5 function min(x,y:longint):longint;
6 begin
7 if x < y then exit(x)
8 else exit(y);
9 end ;
10 begin
11 readln(n,m);
12 for i: = 1 to n do // 初始化f數組
13 read(f[i, 0 ]);
14 for j: = 1 to trunc(ln(n) / ln( 2 )) do // 循環j的長度
15 for i: = 1 to n - 1 << j + 1 do // i的最大值n - 1 << j + 1
16 f[i,j]: = min(f[i,j - 1 ],f[i + 1 << (j - 1 ),j - 1 ]); // 動態規劃更新f數組,注意兩個區間
17 for i: = 1 to m do
18 begin
19 readln(l,r);
20 j: = trunc(ln(r - l + 1 ) / ln( 2 )); // j就是圖示中的k
21 write(min(f[l,j],f[r - 1 << j + 1 ,j]), ' ' ); // 跟圖中一樣
22 end ;
23 end .

?

?

?? ? ?終于寫完了~累死了…有什么不對的地方和說得不明白的地方歡迎大家提出!我一定盡快改正!

(Saltless原創,轉載請注明出處)

?

區間第K大值與RMQ問題


更多文章、技術交流、商務合作、聯系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 欧美整片在线观看 | 久久综合九色综合97婷婷女人 | 狠狠久久久久久亚洲综合网 | 日韩在线视频网站 | 热久久这里是精品6免费观看 | 国产日韩欧美在线观看不卡 | 久久久久久久久影院 | 免费一级特黄欧美大片久久网 | xxxxbbbb欧美 | 天天干天天插天天射 | 亚洲精品久久久久综合网 | 日韩免费中文字幕 | 九九热这里只有国产精品 | 亚洲一区二区三区精品影院 | 亚洲国产欧美国产第一区二区三区 | 四虎影视免费永久在线观看黄 | 国产乱人免费视频 | 91免费网站在线看入口黄 | 在线观看国产一区二三区 | 青青青青青国产费线在线观看 | 全部免费特黄特色大片视频 | 久久国产精品夜色 | 国产精品欧美亚洲韩国日本久久 | 九九综合九九综合 | 日本乱中文字幕系列在线观看 | 色青青草原桃花久久综合 | 99久久久久国产精品免费 | 九九re| 亚洲国产成人99精品激情在线 | 国产亚洲午夜精品a一区二区 | 免费一级毛片麻豆精品 | 欧美亚洲另类久久综合 | 天天艹夜夜艹 | 老司机午夜精品99久久免费 | 久久精品视频一区二区三区 | 男人的天堂在线精品视频 | 狠狠色丁香婷婷久久综合不卡 | 国产精品久久久久国产精品 | 草久视频| 欧美三级在线观看不卡视频 | 51毛片|