[POI2014]HOT-Hotels加强版
这是个长剖练习题。但是重点在于dp。
数据范围达到105,所以直接dp是不可取的。
设fx,i表示x子树内有多少个点距离x为i。
显然有转移方程fx,i+=fy,i−1
根据题设,假设一个节点为t,则题目要求dis(x,t)=dis(y,t)=dis(z,t)的三元组x,y,z的个数。
由于枚举其他元素都不太行,所以考虑枚举t。则三元组的形式肯定是两个点在z的子树,一个点从z上面伸出一个距离k到节点b,在b的一个不包含t的子树内伸出d−k。
当k=0,则三元组x,y,z都在t的子树内。
设gx,i表示x节点子树中有多少个点对的lca到x的距离为d−i。
转移有:两个儿子在同一个儿子的子树中,在不同儿子的子树中。
第一个转移:gx,i+=gy,i+1。
第二个转移:gx,i+=fy,i−1∗fz,i−1,其中y,z分属x的不同子树。
统计答案时,统计三个点都在当前点的子树内,或者一个点伸出当前子树,并且在x的子树内。
第一个贡献是gx,0。
第二个贡献为fx,j−1∗gy,j+1,其中y,z分属x的不同子树。
这部分是统计以x为三个点的lca的答案。
如下图:
对每个节点都做一次这个dp。
直接做是O(n2)的。但是可以长短链剖分,时间复杂度降到O(n)
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步