NPSC 2021 高中組 pD題解

連結1
連結2

題解

首先轉換題目如下:

給定序列 a1,a2,,ana_1,a_2,\dots,a_nb1,b2,,bkb_1,b_2,\dots,b_k ,對於 aa 序列,定義一個區間的分數 cost([l,r))=al,al+1,,ar1,b1,b2,,bk\text{cost}([l,r))=a_l,a_{l+1},\dots,a_{r-1},b_1,b_2,\dots,b_k 中前 rlr-l 大元素的和。求出最大分數。

可以驗證 cost\text{cost} 符合 Monge condition ,那用來解決此問題的演算法就多了,於是可以先想 cost\text{cost} 要怎麼很快的算出來。
最簡單的方法當然就是持久化線段樹算前 rlr-l 大,每次操作時間複雜度是 O(log(n+k))\mathcal{O}(\log (n+k)) ,而且可以隨機存取式的隨意算cost,這樣就可以使用 SMAWK 演算法在 O(nlog(n+k))\mathcal{O}(n \log (n+k)) 的時間做完,但空間需要 O(nlogn)\mathcal{O}(n \log n) 。所以可以考慮使用 sliding window 算 cost ,會有非常大的可能可以把空間壓到線性。
但在使用 sliding window 算 cost 的時候,只能使用轉移點單調 (Monotone Minima) 或是簡易版 LARSCH ,兩者的時間複雜度皆為 O(f×nlogn)\mathcal{O}(f \times n \log n)ff 為 sliding window 移動一次和算答案的時間。因為這題 n106n \le 10^6 ,所以我們希望 f=O(1)f=\mathcal{O}(1)
如果存在一個 sliding window 能用 O(1)\mathcal{O}(1) 的時間加入元素以及計算答案,那就能在 O(n)\mathcal{O}(n) 的時間內解決 Maximum Gap\text{Maximum Gap} 問題,但此問題在 algebraic computation tree model 下有 Ω(nlogn)\Omega (n \log n) 的時間複雜度下界[1],所以加入元素的 sliding window 大概做不到 O(1)\mathcal{O}(1)

既然加入元素不行,那可以改成考慮刪除。先花 O((n+k)log(n+k))\mathcal{O}((n+k)\log(n+k)) 的時間將 aabb 的元素一起由大到小排成長度為 n+kn+k 的序列,將這個序列用 linked list 維護,因為 sliding window 在移動時 rlr-l 只會改變 11 ,所以可以做到 O(1)\mathcal{O}(1) 刪除,且刪除後新的前 rlr-l 大元素和也能在 O(1)\mathcal{O}(1) 維護。
轉移點單調和簡易版 LARSCH 的 sliding window 移動順序都支援使用只能刪除和回滾的 sliding window ,所以只須套用這兩個演算法其中之一就可以把此問題做到 O((n+k)log(n+k))\mathcal{O}((n+k) \log (n+k)) 時間 O(n+k)\mathcal{O}(n+k) 空間。

實作細節的部份,可以跟每個節點說遞迴離開的時候要把 sliding window 復原成遞迴進這個節點時的樣子,會好想以及好寫很多。

一些廢話

原本我是寫簡易版 LARSCH ,需要兩個 sliding window ,想實作加寫搞了三個小時(太笨想很久才想到上面提的實作細節),然後才發現其實可以轉移點單調。
寫這篇 blog 的時候我 hexo 的 mathjax 爛了,遂改用 katex 。
改完 katex 之後發現我的 footnote 爆了,所以就開始改改改改改,改到連 markdown 的 renderer 都換了。我花在修 blog 的時間都比我寫這題的扣的時間還要長==


  1. Lee, D. T., and Ying-Fung Wu. “Geometric complexity of some location problems.” Algorithmica 1.1 (1986): 193-211. ↩︎