NOI2016 王國飲水記
NOI2016 王國飲水記
如何不寫斜優/決策單調性,用暴力通過此題。。(大霧)
首先我們只需要考慮 \(h_i>h_1\) 的點。
然後考慮 \(K\) 足夠大的點,我們手玩一段時間,發現將這些剩餘點保留下來並排序,最優決策一定是將他們依次和 \(1\) 聯通。
比如樣例中的 \(1,3,4\),假設可以操作 \(2\) 次及以上,那麼最優決策一定是依次連線 \(1,3\) 得到 \(2\),然後連線 \(2,4\) 得到 \(3\)
對於 \(K\) 並非足夠大的點,先將剩餘點從小到大排序,不難發現每次的連通操作必然是將 \(1\) 和一段區間 \([l,r]\) 聯通,同時不存在一個點被連兩次(顯然不優)
感性上理解大概可以通過調整法,知道這個性質之後我們可以寫一個 Dp 了:(方便起見,下文的 \(h\) 陣列是僅保留大於 \(h_1\) 的元素且已經排好序,下標從 \(2\) 開始的陣列,而 \(S\) 為其字首和)
設 \(f_{i,j}\) 表示考慮到 \([2,i]\),操作了 \(j\) 次的最優解,那麼轉移形如 \(f_{i,j}=(f_{k,j-1}+S_i-S_k)/(i-k+1)\)
然而要進行高精度小數運算,我們得到了一個 \(\mathcal O(n^2Kp)\) 的做法,非常幸運的是他可以過 \(n\le 100\) 的測試點。
然後我們將最優決策打個表,會發現大概是這樣的例子(以樣例 \(3\)
[100, 100]
[99, 99]
[98, 98]
...
[65, 66]
[62, 64]
[50, 61]
然後發現好像長度不是 \(1\) 的區間非常少?而且決策應該是從某個位置開始的字尾,都會被選中。
我們大膽猜測長度不為 \(1\) 的區間只有 \(\log\) 個(實際上是調參之後知道的),於是 Dp 的第二個維度可以降低成 \(\log\),便得到了一個 \(\mathcal O(n^2\log np)\) 的做法。(大概是預處理 Dp 陣列,然後列舉之前用了多少次,然後剩餘部分一直除以 \(2\))
然後造一點隨機資料,繼續打表,然後發現最大的區間的長度也很小?
於是轉移的時候 \(k\)
於是得到了一個 \(\mathcal O(n\log n\times c\cdot p)\) 的做法。
然後我們發現,之所以需要高精度小數,是因為我們經常除以 \(x\),而且除以次數高達 \(K\) 次,然而如果只考慮預處理部分的 \(O(n\log n\times c)\) 的 Dp,我們發現我們只會除以 \(\log\) 次,換而言之沒有必要用高精度小數。。。
於是這個部分用 long double 把答案存下來來比較(當然誤差很大但是不影響),然後我們將決策點記錄下來,最後還原答案的時候通過高精度實現即可。
最終複雜度是 \(\mathcal O(n\log n\times p+n\log n\times c)\),跑得非常快,我的 \(c\) 設的是 \(100\),是可以通過的。
正常的做法應該是考慮:
\[\frac{dp_j+S_i-S_j}{i-j+1}<\frac{dp_k+S_i-S_k}{i-k+1} \]
對於每個點 \(j\) 和 \(k\) 我們將其視為 \((j-1,dp_j-S_j)\),那麼不難發現這個是最大的 \((i,S_i)\) 與點集 \(S\) 中的斜率最大值。
可以三分交點解決。