第二屆飲料盃解題手冊 Beverage Cup II Solution Manual

H - Tomato's Criterion

題目大意

夢月解題目會根據夢月法則?如果題目需要花費大於 的時間,則定義題目難度為 hard,反之為 easy。大頭蕃準備 個題目請求夢月協助,但隨著每解一題,下一題的難度會隨著疲累值增加,疲累值為一個等差為 個數列。只打算解決 easy 的題目,請問在相同的 下,不同的 分別能解決的最多題數。

題解

如同 Problem B 類似,在固定 的情況下,我們希望能夠求出當答案是 的時候,允許的最大 是多少。我們需要兩件事情:

性質一

固定 的時候,隨著 越大,最大值會越來越往左邊跑。

證明方向很直觀:因為 越大,越左邊的項就會加越多。

性質二

若固定 的時候,最大項為 ,若這個值超過 ,則我們減少 的值:。此時,若 ,那麼 仍是剩下所有關心的數字之中最大值。

理由也很簡單:大家一起減 ,所以原本的最大值還是最大值。

就是那個單調性啊...

所以,事情變得很簡單啦,先假定輸入的序列已經由小到大排好序了。對於一個固定的 ,我們可以記錄每個數字「超過」下一個數字的那個 值是什麼:也就是說,我們想要知道的是

在什麼 的時候會發生。可是這等價於:

因此!我們可以輕鬆知道每一個 相較於下一個數字,當 的時候,它會取得領先的地位。現在我們可以連續看三個數字:若第一個數字 超越第二個數字 的那個 值,比第二個數字超越第三個數字 的那個 值,來得。表示當 超越 的時候, 保證也超越了 ,此時無論如何 都不會是最大值了!

於是這引導我們得到一個 stack 的 solution,對於一個 ,我們維護一個堆疊,從左到右是那些隨著 變大,真的有機會變成最大值的那些 index:,對於相鄰的兩個 ,我們可以輕易計算出,當 的時候,第 項會取代 成為新的最大值。

除了堆疊以外,我們還需要有一個「箭頭」指向對於現在這個 ,最大的 是什麼、最大值出現在哪裡。由於性質一、二,當 變大的時候, 會變小,而且最大值會往後推;因此這個「箭頭」只會隨著 變大而往後推進。

最後,是什麼樣的條件會讓這個「箭頭」往後推呢?假定 是當前的最大值,我們可以輕易算出滿足題目要求的最大 如果它比 來得大,表示目前這個 很安穩(的確是當前最大值);若該值相較之下比較小,表示在這個 的時候,最大值另有其人,此時令 ,繼續檢查下一個

當然,隨著 增加,若最後一個 被 pop 掉了,也要記得把這個「箭頭」拉回來。整個演算法的時間複雜度便是排序 + 堆疊 + 詢問二分搜的時間:。很棒的小品演算法對吧 :)