1. 程式人生 > >[CF 468 Div.1D]Valid Sets

[CF 468 Div.1D]Valid Sets

沒有 一起 就會 div 情況 inline 貪心 limit clas

題意

一個\(n\)個節點的樹,邊有邊權,求一個字典序最小的排列\(p\),令\(\sum_{i=1}^n\limits dis(i,p_i)\)最大

分析

我們考慮\(dis(i,p_i)\)實際上可以拆成三段:\(\sum dep(i)+dep(p_i)-2dep_{lca(i,p_i)}=2\sum dep_i-2\sum dep_{lca(i,p_i)}\)

考慮選重心作為根,那麽就可以平衡地配對起來,讓不同子樹之間的配對,使得後面那一項變成\(0\),那麽整個式子就最大。那麽這時這個答案就很容算出來,但是怎麽讓字典序最小呢?

考慮我們把root刪掉的話,那麽我們要最小就需要滿足兩個需求:

  • 每次給某個\(i\)\(p_i\)選一個最小的\(j\),同時這個\(j\)還不能在和\(i\)同一棵子樹裏面
  • 不能在某個時刻對於某個\(i\)我們不能選點匹配了,也就是我們對於某些子樹我們可能需要優先考慮,這時需要優先滿足貢獻最大的需求

先考慮“合法解”滿足的條件。什麽時候我們需要優先考慮某些子樹呢?我們考慮目前已經確定了排列的前\(i\)項,一個子樹裏面有\(t\)個大於\(i\)的節點(肯定都沒配對),這個子樹裏面還有\(x\)個沒被配對的節點(沒被前面的某個\(p\)選中),那麽實際配對節點一共有\(n-i\)個,但是不能配對同一棵子樹裏面的,所以實際可以配對的只有\(n-i-x\)

個,還未配對的\(t\)個節點必須有配對。

所以當\(t+x\leq n-i\)的時候才行。然而如果一棵子樹出現\(t+x=n-i\)的時候就很關鍵了。因為\(i\)在一直變大,右邊一直在變小,如果左邊不能一起變小的話就完蛋了。那麽要麽就是\(t\)要麽就是\(x\)能夠減\(1\),那麽這個等式其實就會一直滿足了!

我們考慮用set維護下所有子樹的\(t+x\),然後考慮有沒有滿足等式的子樹,然後如果有,而且如果\(i\)在這棵子樹裏就照做,反之必須要找一個\(j\)在這棵子樹裏。剩下的情況上面已經討論過了。

對於找最小的貪心,可以用線段樹,同一棵子樹裏面按照編號放進一個區間裏面,每次指針往後移即可,而對於根可以和任意節點(包括自己)配對,需要特殊考慮。

[CF 468 Div.1D]Valid Sets