$\text{ZJOI}\ 2019$ 半年过去了,发现当时的自己真的好菜,考场上只能打打暴力。
于是我决定补这道题的坑。
Description
九条可怜是一个喜欢规律的女孩子。按照规律,第二题应该是一道和数据结构有关的题。
在一个遥远的国度,有 $n$ 个城市。城市之间有 $n - 1$ 条双向道路,这些道路保证了任何两个城市之间都能直接或者间接地到达。
在上古时代,这 $n$ 个城市之间处于战争状态。在高度闭塞的环境中,每个城市都发展出了自己的语言。而在王国统一之后,语言不通给王国的发展带来了极大的阻碍。为了改善这种情况,国王下令设计了 $m$ 种通用语,并进行了 $m$ 次语言统一工作。在第 $i$ 次统一工作中,一名大臣从城市 $s_i$ 出发,沿着最短的路径走到了 $t_i$,教会了沿途所有城市(包括 $s_i, t_i$)使用第 $i$ 个通用语。
一旦有了共通的语言,那么城市之间就可以开展贸易活动了。两个城市 $u_i, v_i$ 之间可以开展贸易活动当且仅当存在一种通用语 $L$ 满足 $u_i$ 到 $v_i$ 最短路上的所有城市(包括 $u_i, v_i$),都会使用 $L$。
为了衡量语言统一工作的效果,国王想让你计算有多少对城市 $(u, v)$,他们之间可以开展贸易活动。
Solution
考虑求出每个点 $u$ 能够到达多少不同的点 $a[u]$ ,则答案为 $\displaystyle \frac{\sum a[u]} {2}$ 。
$c[x][y]$ 表示 $x$ 与 $y$ 是否可达。
先树剖,动态开点线段树维护上面那个东西,对一条路径 $(u, v)$ 上的所有点都进行区间修改,复杂度 $\mathcal{O} (n ^ 2 \log ^ 2 n)$ ,很优秀。
可是这样还是只能拿 $20$ 分,差一点(也就一个 n 的差距),如果能优化一下就好了。
仔细想一想,会发现这东西是一个类似树上差分的过程,若 $c[x][y]$ 的真正意义是 $x$ 被 $y$ 覆盖了几次,那么我们就相当于在 $u$ 与 $v$ 同时修改,回溯时在 $fa[lca_{u, v}]$ 处消除影响。线段树合并可以很好地帮助我们解决这个问题。
有一个比较巧妙的想法是看了题解之后才了解的,就是我们 $\text{pushup}$ 的时候只需要关注这个节点的标记是否是正的,这样可以省去 $\text{pushdown}$ 。
还有一个稍微值得注意的地方:对于某个点路径修改时,你势必会对其本身也进行修改,而始终没被走过的点则不会被自己修改,我们在统计答案时会出现问题,那么我们不如强制对于每个点修改其本身,最后减去即可(。
Code
1 |
|