标签:题目 连通 节点 块大小 表示 sum dfs 排序 mat
~~ 话说,本题考场想出三只\(log\)的暴力做法,被卡成暴力了。~~
首先考虑枚举每一个点,计算这个点可以和多少点进行交易。
将所有经过该点的路径\(s,t\)拿出,那么这些极远的\(s,t\)构成的连通块大小\(sz - 1\)就是答案。
由\(Codeforces\)的\(异象石\)那题可以想到,若一些点集按照\(dfs\)序排序,那么这些点构成连通块大小就是
\(\frac{1}{2} (dist(a_1 , a_2) + dist(a_2,a_3) + ... + dist(a_{k-1} , a_k) + dist(a_k,a_1))\)
考虑对于每一个节点开一棵线段树,其叶子节点\(i\)表示\(dfs\)序为\(i\)的极远点出现次数。
线段树中存储\(3\)个值\(lp,rp,Sum\)分别表示当前存在的大于\(0\)的最小下标和最大下标,和不算头尾的连通块大小。
由于路径条数为\(m\),显然我们可以用可持久化线段树来维护这\(n\)棵线段树,使得空间复杂度为\(O(m log_2 n)\)
利用树上差分的思想,对于每一条\(s,t\)的路径,我们先在\(s\) 和\(t\)所在的线段树中将\(dfn[s]\)和\(dfn[t]\)两个点单点\(+1\)
然后在\(father(lca(s,t))\)的节点,将\(dfn[s]\)和\(dfn[t]\)两个点单点\(-2\)。
于是,我们可以自下往上去统计每个节点的答案。
每一次,我们需要对该节点的所有子树进行线段树合并,然后询问这个节点的答案,将其累加进总个数中。
这样,我们就完成了无序数对的统计,那么此时答案除以\(2\)就是最终的答案。
由于\(n\)次线段树合并节点总数是\(m\)个,所以需要时间复杂度为\(O(m log_2 n)\)
由于\(m\)次线段单点修改,使用\(O(1)\)的\(LCA\)实现,所以需要时间复杂度为\(O(m log_2 n)\)
所以,本题的总时间复杂度就是\(O(m log_2 n)\)
标签:题目 连通 节点 块大小 表示 sum dfs 排序 mat
原文地址:https://www.cnblogs.com/ljc20020730/p/11623520.html