做題筆記
為了監督自己做題時寫思路以集中注意力,從而提高效率,同時簡單記錄解法,防止以後看不懂自己程式碼特開此文。
只記錄簡單做法,為防止長度過長載入速度慢,所以就不貼程式碼了,反正到處都存了。
CF1059E Split the Tree
簡單 2400 的題,做題時比較浮躁,靜不下來,做了比較久。
考慮到每個點必然包含在一條垂直路徑,根節點必然是垂直路徑的頂端。
定義 f[i] 表示以 i 號點為垂直路徑頂端點,i 的子樹內的節點全覆蓋的最少垂直路徑數量。
顯然滿足
\(\sum_{v \in son_x} f_v\) <= f_x <= \(\sum_{v \in son_x} f_v\) + 1 即要麼單飛,要麼與下面某條路徑合併
轉移即判斷能否找到一個單飛轉移點與當前點形成路徑滿足條件。
由此可知,單飛的越晚越優,即能不單飛就不單飛,既把單飛機會留給之後使轉移更多,又讓當前位置答案更小
由此發現,當答案最優時,單飛與否的狀態也是不劣的
明顯,當確定一個點單飛後,做一個差分維護是否單飛
可以倍增解決。
複雜度 \(O(n \log n)\)
[清北學堂] 校門外的樹
研究標程把這道題弄明白了,於是來寫一篇題解。
題意:
詢問一個區間內的元素的最小差值。
分析本題,發現能夠對答案產生貢獻的數對具有 \(n^2\) 個,但是其中存在大量的無用的數對狀態。
舉個例子,對於點 \(i,j\) ,滿足 \(h_i < h_j\)
類似地,我們考慮能否進一步減少我們的有用的數對數量。
考慮 \(k>j , h_k < h_j\) ,發現這樣的一些 \(k\) 並不完全可能與 \(i\) 產生貢獻,因為這些數有可能與 \(j\) 組成數對會答案產生更優秀的貢獻。
簡單分析可以發現,當 \(h_k < (h_j + h_i) / 2\) 時,\(i,k\) 才不一定劣。
按照上述分析不斷迭代下去,容易發現,對於每個 \(i\)
同理對 \(j > i , h_j < h_i\) 的 \(j\) 尋找不一定劣的數對。
因此有用的數對個數就被壓縮到了 \(\log M\)(\(M\) 為值域) 對。
考慮尋找這些數對。只用開一棵動態開點線段樹從後往前掃一遍,每次尋找滿足不一定劣值域範圍的最近的位置就好了。
找到數對後,離線詢問,左端點從大到小排序掃一遍,求符合範圍的數對權值最小值,用樹狀陣列維護一下就好了。