簡單樹上問題


P1099

直接把直徑揪出來從一邊到一邊掃過去就行了。

記錄

P5659

按照字典序貪心,對每個點維護相鄰的邊的刪除順序, 實際上細節並不多。

記錄

P5666

考慮計算每個點作爲重心的次數。

首先把隨便一個重心拿出來做根, 然後顯然 x 要想作爲重心就不能切 x 子樹裏的邊。(這一步真 tm 妙

那麼剩下的情況就是切邊後,

  1. x 和原來的根不在一個連通塊裏
  2. x 和原來的根在一個連通塊裏

如圖。

louis

以下用 \(siz_x\) 表示以 x 爲根的子樹的節點個數。

對於切斷的邊 \(e\), 稱上面的那個點爲 \(up_e\), 下面的那個點爲 \(down_e\)

\(g_x = \max\limits_{y\in son(x)}\{siz_y\}\)

使用的重心判斷方法是去掉其後任意連通塊的大小乘 2 後都不超過整棵樹的大小。

那麼對於情況 1, 如果 x 爲重心, 那麼

  1. \(2\times g_x\le siz_{down_e}\)
  2. \(2\times (siz_{down_e}-siz_x)\le siz_{down_e}\), 即 \(2\times siz_x\ge siz_{down_e}\)

對於情況 2, 如果 x 爲重心, 那麼

  1. \(2\times g_x \le siz_{rt}-siz_{down_e}\)
  2. \(2\times(siz_{rt}-siz_{down_e}-siz_x)\le siz_{rt}-siz_{down_e}\), 即 \(2\times siz_x\ge siz_{rt}-siz_{down_e}\)

特別地, 對於根,設其最大子樹的根爲 u, 次大子樹的根爲 v, 若刪去的邊不是 u 裏面的也沒有把 u 割出去, 那麼需要滿足 \(2\times siz_u\le siz_{rt}-siz_{down_e}\); 若使 \(siz_u\) 變化了或直接沒有了, 顯然 u 這個子樹是滿足條件的, 那麼剩下的就是要判斷剩下的子樹, 即 \(2\times siz_v\le siz_{rt}-siz_{down_e}\)

可以發現都是值域上區間查詢的形式, 不過要差分出正確的數據結構。

具體地, 對於情況 1, dfs 時維護到根的樹狀數組即可;對於情況 2, 維護全局的樹狀數組, dfs 時維護到根的樹狀數組, 利用樹上差分差分出子樹的樹狀數組。

挺簡單的, 代碼也不難寫。

記錄

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章