其實兩個東西都是堆。區別只不過一個是利用差值等巧妙設計等效權值,另外一個則單純進行判斷。html
反悔自動機post
(名字是我本身起的)url
貪心是不能反悔的。由於它就是選擇當前的最優解。spa
可是若是當前最優解不是全局最優解怎麼辦?設計
咱們能夠設計一種反悔的方法,而且和貪心的手法結合。htm
使得貪心隨便選擇,均可以達到正解。blog
姑且叫反悔自動機。get
基本的設計思路是:it
每次選擇當前直觀上最接近最優解的方案。class
可是發現不對。不是最優子結構
而後想辦法怎麼支持自動反悔。
0.邊有邊權,樹上選擇k個邊不相交的路徑,總和最大(權值有正有負)
求k次樹的直徑,每次把直徑上的邊權取反便可
1.經典問題:CF865D Buy Low Sell High
每次用最小的買入,等到一個能夠賺錢的天就賣出。
不對是由於:可能這個買入的股票要等到後面更貴的那一天再賣出。
利用作差,C-A=B-A+C-B,等效轉化
用最小的買最大的,而後把差值計入答案,把B放進去兩次,再取B爲最小的時候,C-B的差值計入ans,至關於用A買入以C賣出
至關於B沒有用,因此額外再加入一次B,以防後面須要用B買入再D賣出。
2.相似的:
BZOJ 2151
• 有一個長度爲n的環,選擇m個兩兩不相鄰的位置。
• 每一個位置都有一個價值Vi,若是選擇這個位置就能夠獲得Vi的價
值。
• 求最大的價值總和,或輸出無解。
直觀來看,每次選擇能選擇的最大的價值。
爲何不對?由於可能選擇了這個最大的,鄰居就不能選擇。例如1,5,6,5選擇了6,就只能再選擇1,不如5,5
並且,這個貪心的錯誤的點就是這裏。對於最優解位於其餘的位置上的狀況,這種貪心都是成立的。
考慮怎麼支持反悔。
仍是利用差值。
用雙向鏈表維護相鄰的關係。用堆維護全部權值的最大值。
選擇了A,把W[L[A]+W[R[A]-W[A]建成一個新的點P,令這個P的L,R分別是:L[L[A]],R[R[A]],而後刪掉L[A],R[A],
每次取最大值便可。
由於,若是有a,b,c,d,(緊挨着就是相鄰),而且a+c>b+d,那麼,就有a+c-b>d
因此,即便咱們先選擇了b,可是因爲a+c-b>d,咱們會接着選擇a+c-b,就至關於選擇a+c
反悔堆:
(名字也是我本身起的)(其實就是一個堆)
這個不是無腦地隨便貪心了。由於沒有什麼等效權值的替換。
其實思路差很少。
咱們仍是按照一個貪心策略貪心,而後找出來不足。
想辦法反悔。
和反悔自動機不一樣的是,這個要人工反悔。
例題: