P2664 树上游戏(点分治/计数题计算贡献/树上差分)
P2664 樹上游戲
對于樹上n個點,每個點有不同顏色,求解每個點到其他點的路徑上不同顏色個數之和。
首先看到這種樹上點對問題,我們可以想到點分治,然后考慮每次分治如何求解答案,本質上就是一個數顏色的問題,然后我們采用類似的思路,考慮每個顏色第一次出現時的貢獻,但是現在的問題就在于一條鏈是沒有前后的,所以我們可能需要一些計算。
首先對于分治中心的貢獻計算,我們可以從中心開始dfs,在每個顏色第一次出現的地方有size的貢獻。
然后考慮每個子樹內部的點,對于在從當前點到分治中心的鏈上出現過的顏色,我們直接將其統(tǒng)計為cnt(sizrt?sizx)cnt(siz_{rt}-siz_{x})cnt(sizrt??sizx?)然后考慮沒有在這一段出現的顏色,那就是之前一開始在其他子樹內部出現的貢獻,但是要減去在當前這條鏈上已經出現的顏色貢獻和當前所在子樹內部的顏色貢獻。
這個具體實現的確是很麻煩,首先一步dfs求解出所有子樹的貢獻之和,對應顏色的總貢獻,以及每個子樹分別產生的貢獻之和,然后具體處理每個子樹內的點時候,先dfs這個子樹,求解該子樹對應顏色的貢獻,然后再dfs一邊該子樹分別計算每個點的答案
ansi=tot?sumu?∑k∈Scol[k]+cnt?(sizrt?sizu)ans_i=tot-sum_u-\sum_{k\in{S}}col[k]+cnt*(siz_rt-siz_u)ansi?=tot?sumu??k∈S∑?col[k]+cnt?(sizr?t?sizu?)
這就是最終的結果
其實整理一下發(fā)現我們應該這樣思考,首先數顏色問題都是考慮第一次或者最后一次出現的貢獻,那么現在問題需要求解每個點的答案,我們就考慮每個點的鏈,分為兩類顏色,一類第一次出現在當前子樹他們的貢獻可以直接計算,一類出現在其他子樹,他們的貢獻就是對應的子樹大小之和,所以我們想到這樣統(tǒng)計
O(n)的fansy做法:
現在我們直接不考慮點分治,直接考慮每種顏色的貢獻,可以發(fā)現去掉某種顏色后樹會變成若干個連通塊,并且每個連通塊仍然是一顆樹,然后對于每個連通塊的貢獻就是siz?sizusiz-siz_usiz?sizu?那么對于每個點的答案就應該是cnt?n?∑csizc,icnt*n-\sum_{c}siz_{c,i}cnt?n?∑c?sizc,i?然后我們考慮如何統(tǒng)計,首先將每個顏色的貢獻放在深度最小的點上,這樣子就是一個樹上差分了,只不過這里是子樹覆蓋,那么我們只需要在dfs過程中維護dfs棧的每種顏色的對應信息即可。
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎勵來咯,堅持創(chuàng)作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的P2664 树上游戏(点分治/计数题计算贡献/树上差分)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 减肥晚餐吃什么瘦得快
- 下一篇: P3835 【模板】可持久化平衡树