CF504E Misha and LCP on Tree

CF504E Misha and LCP on Tree。

经典套路:哈希+二分,然后还需要述链剖分快速维护对比。

思路好想,代码不好写

代码好难调。。。

这道题我们需要求一条路径的哈希值,需要求出根节点到他的哈希值,还有他到根节点的,然后要写半天。

树上启发式合并

就不讲了,看这道题:

P4149 [IOI 2011] Race

P4149 [IOI 2011] Race。

我们发现如果设定合并内容为到当前节点的距离,会很难转移。

所以我们直接存这个点到根节点的长度,然后最后的答案就需要两点的距离减去 LCA 的距离的两倍。

点分治

dsu on tree 是根据子树大小确定最大的子树的贡献直接保留。

而点分治是直接计算重心,用重心进行子树的拆分来完成问题。

这个。

P3806 【模板】点分治

P3806 【模板】点分治。

点分治通过每次选取树的重心作为分治点,将树分解为若干子树递归处理,从而高效统计所有经过或不经过当前重心的路径信息。

P6329 【模板】点分树 / 震波

P6329 【模板】点分树 / 震波。

我们通过点分治每次找重心的方式来对原树进行重构。

将每次找到的重心与上一层的重心缔结父子关系,这样就可以形成一棵 log⁡n\log n 层的树。

  • 性质 11:树是 log⁡n\log n 层的,而且树上所有点的子树大小之和为 O(nlog⁡n)O(n \log n),所以这可以让很多暴力更快。

  • 性质 22:对于任意两点 u,vu,v,唯一可以确定的是 u,vu,v 在点分树上的 LCA 一定在 u→vu→v 的路径上,dis(u,v)=dis(u,lca)+dis(lca,v)dis(u,v)=dis(u,lca)+dis(lca,v)。(这个感性理解一下,如果 LCA 不在就会出现环)。

然后结合这两个性质我们可以做题了。

这道题的思路

首先我们发现每一对节点的 LCA 个数是 log⁡n\log n 级别的,所以考虑枚举 LCA。

∑dis(z,y)≤k−dis(x,z)&LCA(x,y)=zay\sum\limits_{dis(z,y)\leq k-dis(x,z)\&LCA(x,y)=z}a_y

LCA(x,y)=zLCA(x,y)=z,答案就是拿 zz 的子树内到 zz 的距离 ≤k−dis(x,z)\leq k-dis(x,z) 的点权和 −- xx 方向子树中到 zz 的距离 ≤k−dis(x,z)\leq k-dis(x,z) 的点权和。

对每个点 xx 建一棵动态开点线段树,下标为 ii 的位置维护 xx 子树内所有 dis(x,z)=idis(x,z)=i 的 aza_z 的和。

  • 对于 zz 子树内的 xx,区间查询即可。

  • 对于 zz 在 xx 方向上的儿子 ss 的子树,考虑对于每个点再建立一棵动态开点线段树,线段树上下标为 ii 的位置维护 xx 子树内到 faxfa_x 距离 =i=i 的点权和,然后就可以解决了。

查询:从 xx 沿点分树向上,设当前节点为 ss,d=dis⁡(s,x)d = \operatorname{dis}(s, x)。若 d≤kd \le k,则答案加上 w1[s]w1[s] 中距离 ≤k−d\le k-d 的和,减去上一节点 prepre 的 w2[pre]w2[pre] 中距离 ≤k−d\le k-d 的和。

修改:从 xx 沿点分树向上,对每个 ss,w1[s]w1[s] 中下标 dis⁡(s,x)\operatorname{dis}(s, x) 增加权值;若 ss 有父亲 fafa,则 w2[s]w2[s] 中下标 dis⁡(fa,x)\operatorname{dis}(fa, x) 增加权值。

代码太难调了!!!

线段树合并

就是直接模拟合并。

时间复杂度:每一个节点会被合并一次,然后节点数虽然放到线段树上是 log⁡\log 个,但是只会访问这 log⁡\log 个中的一个,然后对于每一个节点,会被合并 log⁡\log 次(可以尝试势能分析)。

P3521 [POI 2011] ROT-Tree Rotations

P3521 [POI 2011] ROT-Tree Rotations。

思路

我们发现,交换这个点只会改变左右子树间的贡献。

所以我们只需要计算所有点的左右子树间的贡献就行了。

对于每一个点,建一个动态开点权值线段树,线段树的合并就可以计算贡献了,左边 ≤mid\le mid 的和右边 ≥mid\ge mid 的进行这种匹配。

简单总结一下,很多时候都是对于原树的结点,每一个都建立一个权值线段树,维护所有权值,进行合并。然后由于插入的权值数量有限,最后的复杂度也没有问题。

P8496 [NOI2022] 众数

这道题就是直接权值线段树,然后加上二分就行了。

至于删除最后一个数就是链表了。

树形 dp

P4577 [FJOI2018] 领导集团问题

P4577 [FJOI2018] 领导集团问题。

这道题的状态设置成答案为 ii 的时候的最好状态。

然后利用到这道题状态的有序性,直接放入 multiset。

思路

注意:部门不必联通!

fx,if_{x,i} 表示在 xx 的子树中选择 ii 个点组成的所有树上 LIS 中,级别值 ww 最小值最大的那一个。

然后利用到这道题状态的有序性。

然后我们建立 multiset fuf_u,里面的数按升序排列后,第 ii 个数表示: 在 uu 的子树中,选 ii 个结点组成合法集合时,这 ii 个结点中最大的权值最小可能是多少。

然后合并就是直接插入,很好理解。

最后答案就是 multiset 的大小。

长链剖分

P4292 [WC2010] 重建计划

P4292 [WC2010] 重建计划。

其实这是一道点分治和长链剖分都能做的题。

常见的 trick:二分答案之后,将所有边权减去 mid 然后使最后答案 ≥0\ge 0。

这道题的状态定义和长链剖分的本质密切相关

这道题需要定义一个 gg 表示在 dfndfn 为 xx 的节点上,到他所在的重链底端的权值和。

然后定义 ff 表示 ii 节点向下走 jj 的路劲权值和减去 gig_i。

然后这样设计是为了同一条重链上的节点可以直接转移。