[2021.1.27多校省选模拟10]跑步
经典的树上启发式合并题目,维护对应子树的从当前点到子树内一个节点这个链待定,其他部分已经确定的方案数,这个东西按照对应点到根节点的路径点权和为下标存在一个权值线段树中,然后维护这个权值线段树可以线段树合并。
然后考虑如何统计链完全匹配完成时的方案数,我们可以考虑每次合并前查询答案,相当于是对一段后缀进行询问权值和,可以进行线段树上二分,因为我们要求权值和大于等于0。然后先询问再合并,这样可以保证任意两个链都会被统计到,这个套路还是比较常见的,而且这样的复杂度就变成了O(nlognlogn)因为轻儿子总共的大小是O(nlogn)级别的,然后我们还需要对于每个点进行线段树上二分所以一共有两个log。
细节要注意我们这里处理每次继承重儿子的线段树,然后可以暴力枚举其他轻儿子,然后合并的时候对应的权值需要进行修改,因为一个链的贡献应该是除了这两个儿子之外其他儿子的方案数乘积,然而我们查询时对应的子树是不同的,但是我们发现对于还未加入的轻儿子都会要乘,所以我们只需要每次维护每个点为已经加入的其他轻儿子的权值乘积,这个可以通过维护乘法标记处理。
然后还有一点细节就是对于单独的链不是合并形成的链需要处理,对于轻儿子可以一开始把当前节点加入权值线段树,之后就会计算,对于重儿子需要特殊处理一下就好。
最后再特殊处理当前一个节点作为链的贡献即可。