CF2018E2 Solution
先考慮E1的做法。
首先我們如果欽定一組 \(k\) 條線段的話,容易求出最大組數。
簡單來講就是將所有端點按照右端點排序,這樣只需要考慮一個偏序,然後掃描,將區間 \([l_i,r_i]\) 加一,當發現某個點的值為 \(k\) 時,就說明分成了一組方案。
此時我們一定清空,然後記錄當前的 \(r\),也就是後面選的點左端點不得小於等於 \(r\)。
直覺上,這樣貪心選擇一定更優。設這樣的答案為 \(k\)。
我們的答案可以表示為 \(\max k·f(k)\)。
而我們發現,對於一個固定的 \(f(k)\),它是隨著 \(k\) 單調不升的,這很顯然。
所以對於一個固定的 \(f(k)\),可以透過二分的形式得到 \(\max k\),這樣就足以在 \(O(n\log n\sqrt{n\log n})\) 解決問題,足以透過 E1。
事實上在這裡可以透過整體二分求得所有的 \(f(k)\),它的複雜度足以降至 \(O(n^{1.5}\log n)\),這是因為在第 \(d\) 層時,值域被劃分為了 \(O(\frac{n}{2^d})\) 長的 \(2^d\) 段,在 \([\frac{n}{2^{d/2}},n]\) 範圍內 \(f\le 2^{d/2}\),而 \([1,\frac{n}{2^{d/2}}]\) 又僅有 \(O(2^{d/2})\) 段,所以這裡總段數是 \(O(2^{d/2})\) 的,總的整體二分複雜度就是 \(O(\sum^{\log_2n} 2^{d/2})=O(\sqrt n)\) 的。
那麼考慮最佳化線段樹這個過程,一個很重要的技巧是,我們只關心全域性最大值,以及字尾加。
那麼可以使用並查集,維護字尾最大值出現位置。
首先,我們使端點互不相同,具體地,將原本的所有端點排序(如果是相同值,原本為右端點的放在後面),然後依次給其賦值 \(1\sim 2n\)。
這顯然不會破壞相交關係也不會新增。
然後我們利用並查集維護差分,每次字尾加只會造成新的 \(r\) 成為一個字尾最大值,以及增加的最大的 \(< l\) 的字尾最大值端點刪去。
利用並查集維護這個即可。