Codeforces 1486F Pairs of Paths


Description

 給定一棵大小為 $n$ 的樹和 $m$ 條鏈 $(u, v)$。統計有多少對鏈,滿足這兩條鏈恰好有一個交點。

$n, m \le 3 \times 10^5$

Solution

不妨欽定 $1$ 為根分析。

考慮如下問題:恰有一個交點的兩條鏈會長成什么樣子。

其實分為兩種情況:一是它們的 $\text{LCA}$ 相同,而是它們的 $\text{LCA}$ 不同。如下圖所示。

左圖中 LCA 表示兩條鏈 $A, B$ 公共的 $\text{LCA}$,而右圖中 LCA 則是 $A$ 的 $\text{LCA}$(也就是兩條鏈的 $\text{LCA}$ 中較深的那一個)。

現在,我們對於給定的一條鏈 $(u, v)$,求出它的三個值:$lca, a, b$。$a$ 表示 $u$ 在 $lca$ 的哪一棵子樹中,$b$ 表示 $v$ 在 $lca$ 的哪一棵子樹中。或者可以理解為,設 $u$ 與 $lca$ 的深度差為 $k$,則 $a$ 是 $u$ 的 $k-1$ 級祖先,$b$ 是 $v$ 的 $k-1$ 級祖先。值得注意的是,可能 $u, v$ 互為祖先—后代關系,比如 $u$ 是 $v$ 的祖先,那么我們可以欽定 $a$ 為一個新開的點,避免對后面的統計造成影響。同時為了方便,請確保 $a<b$,這一點可以通過交換 $u, v$ 和 $a, b$ 很簡單的達到。

現在,我們分別考慮求出上面兩種情況對答案的貢獻。

先考慮第一種情況,我們可以把所有的鏈先按 $lca$ 的深度,再按 $lca$ 排序。對於 $lca$ 相同的一些鏈,顯然我們求的就是 $\boldsymbol{a_x, b_x, a_y, b_y(a_x<a_y)}$ 互不相同的鏈對 $\boldsymbol{(x, y)}$ 的數量。為了確保不重不漏,我們不妨按照 $a$ 嚴格遞增的順序去一段一段地枚舉鏈 $y$,同時開個桶 $buk_i$ 記錄一下從子樹 $i$ 中伸出來的鏈的條數。每次 $ans \gets ans + cnt - buk_{b_y}$,然后分別把 $buk_{a_y}, buk_{b_y} + 1$ 就好了。上面 $cnt$ 表示的是已經枚舉過的鏈的條數。具體細節參考代碼。

考慮第二種情況,我們依然可以把所有的鏈先按 $lca$ 的深度,再按 $lca$ 排序。設以 $u$ 為根的子樹對應 $\text{DFS}$ 序上 $[\textit{ldf}_u, \textit{rdf}_u]$ 這一段。用樹狀數組維護一個 $\text{DFS}$ 序,每次 $ans \gets ans + \operatorname{Sum}(\textit{ldf}_{lca}, \textit{rdf}_{lca})$,然后如果 $a$ 不是新建的點的話,$ans \gets ans - \operatorname{Sum}(\textit{ldf}_{a}, \textit{rdf}_{a})$,$b$ 同理。最終我們把 $\text{DFS}$ 序上的 $x$ 和 $y$ 位置分別 $+1$ 就可以了。正確性顯然。

按照上面的做法是一個 $\log$ 的,但是通過一些奇技淫巧可以優化成線性,這里不再討論。

代碼實現推薦兔隊長的賽時提交,個人認為寫的很清晰了。


 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM