有的遞推演算法既可以從左向右推也可以從右向左推,這種特性賦予了我們乙個技巧,雙端處理法
當乙個東西對遞推陣列的影響僅限於左半部分或右邊部分,我們可以構造乙個反向遞推的陣列,把不受影響的部分合起來計算
ex最大欄位和
經典的最大子段和問題應該都很熟悉了,那麼如果把這個問題魔改一下,選取兩段不相交的子段,使得他們的和最大,該怎麼做?
先回憶一下最大欄位和的dp做法,記f[i]為以i為右端點的最大欄位和,那麼則可以從左向右遞推出每乙個f,問題解決
那麼如果我們要選取兩段,同時保證它們不相交,是不是可以選擇f最大的兩個點?
當然不行,這裡出現了乙個問題,你無法保證你選取的兩個區間是不相交的,因為f陣列只規定了右端點,而左端點是不確定的
我們希望找到乙個方法,確保兩個區間不相交
乙個簡單的做法就是再跑一邊dp,記g[i]為以i為左端點的最大欄位和
那麼任選兩點i,j(i
這樣我們列舉i,對於每個i,找到max g[j] (j>i),這樣就可以在o(n)的時間內找到最大雙子段和了(i要從n列舉到1,這樣max g[j]就可以遞推了)
ex清理石子
n堆石子排成一列,第i堆有a[i]顆石子,你每次可以在相鄰的兩堆中各取一顆石子,最終要把所有石子全部清除
當然,絕大多數情況下無法清除所有石子,幸好你有一項能力,在開始清理前,你可以交換任意兩堆相鄰的石子
請問你是否可以清理全部石子?(n<=1e5)
如果不考慮交換石子,那麼這會是一道簡單的題
先考慮最左端的石子,你想要清理它,就必須和第二堆一起清理,所以必須a[1]<=a[2],否則無法全部清理
清理完第一堆以後,第二堆變成了實際上的"第一堆",再用類似的方法清理它,以此類推
記f[i]為清理完[1,i-1]後,第i堆剩下的石子數,那麼有解的充要條件就是所有f[i]>=0
下面考慮交換操作對f陣列的影響
不難發現,交換操作只會影響f陣列後面的一部分,如果你交換i和i+1,那麼[1,i-1]不會受到影響
可以採用類似於ex最大欄位和的方法,反著再來乙個g陣列,g[i]表示清理完[i+1,n]後第i堆剩下的石子數量(既然可以從左遞推,那麼也可以從有遞推,因為清理第n堆石子也只有一種方法,和第n-1堆一起清理)
交換後i與i+1後先從左向右清理[1,i-1]再從右向左清理[i+2,n],如果清理過後第i堆和第i+1堆石子數量相等,那麼答案就是yes,否則可能需要交換另一對石子堆才行
有的遞推演算法既可以從左向右推也可以從右向左推,這種特性賦予了我們乙個技巧,雙端處理法
當乙個東西對遞推陣列的影響僅限於左半部分或右邊部分,我們可以構造乙個反向遞推的陣列,把不受影響的部分合起來計算
ex最大欄位和
經典的最大子段和問題應該都很熟悉了,那麼如果把這個問題魔改一下,選取兩段不相交的子段,使得他們的和最大,該怎麼做?
先回憶一下最大欄位和的dp做法,記f[i]為以i為右端點的最大欄位和,那麼則可以從左向右遞推出每乙個f,問題解決
那麼如果我們要選取兩段,同時保證它們不相交,是不是可以選擇f最大的兩個點?
當然不行,這裡出現了乙個問題,你無法保證你選取的兩個區間是不相交的,因為f陣列只規定了右端點,而左端點是不確定的
我們希望找到乙個方法,確保兩個區間不相交
乙個簡單的做法就是再跑一邊dp,記g[i]為以i為左端點的最大欄位和
那麼任選兩點i,j(i
這樣我們列舉i,對於每個i,找到max g[j] (j>i),這樣就可以在o(n)的時間內找到最大雙子段和了(i要從n列舉到1,這樣max g[j]就可以遞推了)
ex清理石子
n堆石子排成一列,第i堆有a[i]顆石子,你每次可以在相鄰的兩堆中各取一顆石子,最終要把所有石子全部清除
當然,絕大多數情況下無法清除所有石子,幸好你有一項能力,在開始清理前,你可以交換任意兩堆相鄰的石子
請問你是否可以清理全部石子?(n<=1e5)
如果不考慮交換石子,那麼這會是一道簡單的題
先考慮最左端的石子,你想要清理它,就必須和第二堆一起清理,所以必須a[1]<=a[2],否則無法全部清理
清理完第一堆以後,第二堆變成了實際上的"第一堆",再用類似的方法清理它,以此類推
記f[i]為清理完[1,i-1]後,第i堆剩下的石子數,那麼有解的充要條件就是所有f[i]>=0
下面考慮交換操作對f陣列的影響
不難發現,交換操作只會影響f陣列後面的一部分,如果你交換i和i+1,那麼[1,i-1]不會受到影響
可以採用類似於ex最大欄位和的方法,反著再來乙個g陣列,g[i]表示清理完[i+1,n]後第i堆剩下的石子數量(既然可以從左遞推,那麼也可以從有遞推,因為清理第n堆石子也只有一種方法,和第n-1堆一起清理)
交換後i與i+1後先從左向右清理[1,i-1]再從右向左清理[i+2,n],如果清理過後第i堆和第i+1堆石子數量相等,那麼答案就是yes,否則可能需要交換另一對石子堆才行
演算法導論 10 1 5 雙端佇列
棧的插入和刪除操作都是在一端進行的,而佇列的插入和刪除卻是在兩頭進行的。另有一種雙端佇列 deque 其兩端都可以做插入和刪除操作。對於乙個用陣列構造的雙端佇列,請寫出四個在兩端進行插入和刪除的操作的過程,要求執行時間都為o 1 next p,l 1 if p l 2 then ret 1 3 el...
演算法題 雙核處理
時間限制 1秒 空間限制 32768k 一種雙核cpu的兩個核能夠同時的處理任務,現在有n個已知資料量的任務需要交給cpu處理,假設已知cpu的每個核1秒可以處理1kb,每個核同時只能處理一項任務。n個任務可以按照任意順序放入cpu進行處理,現在需要設計乙個方案讓cpu處理完這批任務所需的時間最少,...
BWT表的雙端匹配演算法
先對reference取反 gcaga 再對取反後的 reference顛倒位置 agacg reference 右移 cgtctagacg gcgtctagac cgcgtctaga acgcgtctag gacgcgtcta agacgcgtct tagacgcgtc ctagacgcgt tc...