▎前言
首先先來說一下rmb是什麼,當然是人民幣啦。
今天我們要學的這個東西不一般,叫做rmq問題,那麼它和rmb有什麼關係呢?待小編細細說來。
▎前置技能:動態規劃
不會的同志請戳這裡迅速了解動態規劃。
▎rmq問題是什麼
☞『定義』
☞『問題解決:模擬演算法』
rmq只是一類這樣的問題,卻不是一門演算法。
既然是問題,那麼我們就應該解決,但是怎麼解決,怎樣解決,一切先從模擬演算法(直白一點叫暴力)說起。
先來想想模擬演算法怎麼解決,當然是給定區間後直接遍歷,尋找最大/最小值唄。但是別忘了,這種題多次詢問,一直遍歷對於資料規模大的題簡直是杯水車薪。
此時,不得不請出動態規劃。
☞『問題解決:動態規劃』
我們為什麼使用動態規劃呢?先來思考這個問題:為什麼暴力不能滿足需求。
你肯定會說:這還不簡單,暴力慢唄。
但是暴力究竟慢在了**?暴力慢在了沒有完全利用好整個大區間,很多東西都在重複遍歷。
那麼什麼東西能很好的利用大區間呢?我們就會自然的想到了動態規劃(感覺屬於區間動態規劃)。
既然多次詢問,那麼就變向的告訴了我們一定要預處理,這裡我們的動態規劃可以o(n log n)預處理,然後o(1)查詢。
先來思考怎麼設計狀態,最開始小編是這樣想的,既然是區間型動態規劃類問題,那麼就讓f[i][j]表示i~j區間內的最大/最小數吧,(以最大數為例)狀態轉移方程自然就是f[i][j]=max(f[i][k],f[k+1][j])。(k為隨機乙個i~j區間的陣列下標,不過小編更喜歡取中點)
後來發現一本通提高篇上的設計狀態更好,更快捷,我設計的太慢了。一本通提高篇上是這樣處理的:f[i][j]表示i~2j-1區間內的最大/最小數,那麼我們可以仿照之前我的想法,分一半,就是這樣的:
從區間初始和結束位置改成動態規劃的形式後就是這樣的:f[i][j-1]和f[i+2j-1][j-1],有時候奇數和偶數是不一樣的,所以小編的圖可能對這兩個式子來說不太標準。
那麼我們要求的最大最小值就很簡單了。
但是問題又來了,我們如何面對詢問呢?
我們可以以二為底,將這個區間內數字的個數次方(冪的逆運算)為界,進行比較兩個區間大小,**一下:
那麼我們就只要比較出兩個區間中的最大最小值即可。兩個區間改成動態規劃形式就是f[x][log[d]],f[y-(1好了,問題又來了,log怎麼處理,我們先來看一下前10個數的log處理情況:
經過專業調查和探尋後,就會發現log[i]=log[i/2]+1的規律,因此我們可以預處理出log的值。
☞『這麼快的演算法,為什麼還需要其他演算法呢?』
其實這個問題正是這個演算法的弊端,因為不能支援期間修改一些數的值。
而線段樹,樹狀陣列正巧妙的解決了這一弊端。
▎實戰演練:洛谷p1816 忠誠(模板題)
廢話不多說,直接上題:
老管家是乙個聰明能幹的人。他為財主工作了整整10年,財主為了讓自已賬目更加清楚。要求管家每天記k次賬,由於管家聰明能幹,因而管家總是讓財主十分滿意。但是由於一些人的挑撥,財主還是對管家產生了懷疑。於是他決定用一種特別的方法來判斷管家的忠誠,他把每次的賬目按1,2,3…編號,然後不定時的問管家問題,問題是這樣的:在a到b號賬中最少的一筆是多少?為了讓管家沒時間作假他總是一次問多個問題。
輸入格式:
輸入中第一行有兩個數m,n表示有m(m<=100000)筆賬,n表示有n個問題,n<=100000。
第二行為m個數,分別是賬目的錢數
後面n行分別是n個問題,每行有2個數字說明開始結束的賬目編號。
輸出格式:
輸出檔案中為每個問題的答案。具體檢視樣例。
輸入樣例#1: 複製
10 3輸出樣例#1: 複製1 2 3 4 5 6 7 8 9 10
2 73 9
1 10
2 3 1這道題相當好做,就是模板題,所以就不解釋了,直接上**:
1 #include2▎實戰演練:一本通1541:【例 1】數列區間最大值(模板題)using
namespace
std;
3int m,n,a[100000],f[100000][100],x,y,log[100000];4
intmain()512
for(int j=1;j<=16;j++)
13for(int i=1;i+(1
<1
<=m;i++)
14 f[i][j]=min(f[i][j-1],f[i+(1
<
]);15 log[1]=0;16
for(int i=2;i<=100000;i++)
17 log[i]=log[i/2]+1;18
for(int i=1;i<=n;i++)
1924
return0;
25 }
廢話不多說,直接上題:
時間限制: 1000 ms 記憶體限制: 524288 kb
提交數: 638 通過數: 224
輸入一串數字,給你 m
'>
m 個詢問,每次詢問就給你兩個數字 x,y
'>
x,y,要求你說出 x
'>
x 到 y
'>
y 這段區間內的最大數。
第一行兩個整數 n,m
'>
n,m 表示數字的個數和要詢問的次數;
接下來一行為 n
'>
n 個數;
接下來 m
'>
m 行,每行都有兩個整數 x,y
'>
x,y。
輸出共 m
'>
m 行,每行輸出乙個數。
10 23 2 4 5 6 8 1 2 9 7
1 43 8
5對於全部資料,1≤n8
≤105,
1≤m≤
106,1
≤x≤y
≤n'>1≤n≤105
,1≤m≤106
,1≤x≤y≤n
。數字不超過 c/c
++'>c/c++
的 in
t'>
int 範圍。
無這道題只要把忠誠的**改成max就可以了(還稍微有點其他細節),注意會卡常數,不能用cin和cout。**如下:
1 #include2 #include3using
namespace
std;
4int m,n,a[1000000],f[1000000][100],x,y,log[1000000];5
intmain()613
for(int j=1;j<=18;j++)
14for(int i=1;i+(1
<1
<=m;i++)
15 f[i][j]=max(f[i][j-1],f[i+(1
<
]);16 log[1]=0;17
for(int i=2;i<=m;i++)
18 log[i]=log[i>>1]+1;19
for(int i=1;i<=n;i++)
2025
return0;
26 }
極樂技術週報 第十九期
極樂技術週報 第十九期 為什麼程式設計師總是搞混萬聖節和聖誕節?因為.oct 31 dec 25。驗證碼就如同馬奇諾防線一樣,阻擋了爬蟲工程師的正面進攻。隨著爬蟲和反爬蟲雙方圍繞驗證碼的不斷較量,最終導致了驗證碼識別難度的不斷上公升。鏈結位址 一直以來,使用純 css 實現波浪效果都是十分困難的。因...
學習日誌第十九日
學習日誌 姓名 陳長穩 日期 7.27 今日學習任務 今日主要運用昨日講的知識點,點亮開發板上的四個燈。今日任務完成情況 基本完成了nvic中斷基礎介紹,除錯功能printf功能配置介紹以及exti基礎及按鍵實現的學習,並用中斷延時程式完成了控制乙個燈閃爍,以及通過按鍵點亮led燈。今日開發中出現的...
大話IT第十九期 戴爾收購物件大猜想
讓人唏噓的不只是娛樂圈的分分合合,it界的分分合合也不遜色 為什麼這麼說呢?大家先來看看這段戴爾 emc版的 十年 或許就明白了 十年 獻給dell emc舉案齊眉的過往 作詞 戴爾 作曲 圖斯 表演者 戴爾 圖斯 十年之前,我不轉銷你你不收購我 我們還是一樣陪在企業級客戶左右 走過擁擠的華爾街頭 ...