HDU-3415 單調隊列

首先單調隊列就是具有單調性的隊列。。。

算了不廢話了,關於單調隊列這裏有一個對於初學者來說簡單明瞭的博客:鏈接

具體步驟:

  1.  若隊列爲空,將A[i]從隊尾入隊
  2.     若隊列不爲空,將比A[i]大的元素都從隊尾彈出,然後把A[i]入隊
  3.     若隊列不爲空且A[i]大於隊尾,則直接從隊尾把A[i]入隊
if(q.empty())
  q.push_back(A[i]);
else if(q.back()>A[i]){
  while((!q.empty())&&q.back()>A[i]){
    q.pop_back();
  }
  q.push_back(A[i]);
}
else
  q.push_back(A[i]);

可以用數組,也可以用deque,畢竟要做彈出隊尾的操作。(借用上一鏈接博主的原文,如有侵權,請聯繫我,立刪)

再來說HDU-3415這個題:鏈接 https://vjudge.net/problem/HDU-3415

我也找到了一個博主寫的相當詳細明瞭的解析,真好。鏈接

大意呢就是:因爲序列是環狀的,所以可以在序列後面複製前k-1個數字。如果用s[i]來表示複製過後的序列的前i個數的和,那麼任意一個子序列[i..j]的和就等於s[j]-s[i-1]。
對於每一個j,用s[j]減去最小的一個s[i](i>=j-k)就可以得到以j爲終點長度不大於k的和最大的序列了。將原問題轉化爲這樣一個問題後,就可以用單調隊列解決了。
單調隊列即保持隊列中的元素單調遞增(或遞減)的這樣一個隊列,可以從兩頭刪除,只能從隊尾插入。單調隊列的具體作用在於,由於保持隊列中的元素滿足單調性,
對於上述問題中的每個j,可以用O(1)的時間找到對應的s[i]。(保持隊列中的元素單調遞增的話,隊首元素便是所要的元素了)。
維護方法:對於每個j,我們插入s[j-1]的下標,插入時從隊尾插入。爲了保證隊列的單調性,我們從隊尾開始刪除元素,直到隊尾元素對應的值比當前需要插入的s[j-1]小,就將當前元素下標插入到隊尾。之所以可以將之前的隊列尾部元素全部刪除,是因爲它們已經不可能成爲最優的元素了,因爲當前要插入的元素位置比它們靠前,對應的值比它們小。我們要找的,是滿足(i>=j-k)的i中最小的s[i]。在插入元素後,從隊首開始,將不符合限制條件(i<j-k)的元素全部刪除,此時隊列一定不爲空。(因爲剛剛插入了一個一定符合條件的元素)。
 

最後代碼我就不貼了,可以看上一博主的博客,也是爲了感謝博主,幫他提一下訪問量。感謝!

(以上內容兩位博主要是介意,聯繫我立刪)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章