图论专题-专项训练:点分治

1. 前言

本篇博文是作者在学习点分治这一算法的时候做的一些题目的总结。

前置知识:点分治算法。

2. 练习题

题单:

P4178 Tree

考虑点分治。

这道题需要求的是路径长度小于等于 k 的情况,那么在点分治的 Solve 中我们需要做一点改变。

考虑建一棵值域线段树 Tree 用来维护所有当前已经出现过的路径,如果路径长度为 p 的路径出现过,那么就在值域线段树中对应的做一次单点 +1。

那么在点分治的过程中,考虑处理出所有能够出现的路径,假设当前子树处理出的路径为 {tmp},那么对于所有 tmpik,在线段树中查询 [0,ktmpi] 的和就可以了。

一个优化就是如果我们每次 Solve 都要重新建一棵值域线段树,那么建树复杂度就是 O(klogn) 的,因此我们可以考虑采用区间推平的手段,在根节点处打一个 lazy_tag 用来标记当前这一段是否全部为 0(被推平),这样每一次我们只需要在根节点处推平一次就可以了,复杂度降至 O(logn)

Code:Github CodeBase-of-Plozia P4178 Tree.cpp

P2634 [国家集训队]聪聪可可

考虑点分治。

首先这道题一定要看一下样例解释,否则你会发现写完了根本调不出来。

这道题需要注意的几个点:

  • 聪聪和可可是可以选两个相同的点的。
  • (u,v)(v,u) 算作两个不同的点对(uv)。

这样,总的点对个数是 n2,我们只需要统计路径长度为 3 的倍数的路径就好。

对于 (u,u) 这样的点对,显然只有 n 对,在最后计算答案的时候加上就好。

Solve 中开一个 book 数组来统计,其中 booki 表示模 3 为 i 的路径有多少条。

设当前子树统计结果是 tmp,那么这棵子树对答案的贡献就是 2×(tmp0×book0+tmp1×book2+tmp2×book1)+2×tmp0

最后的答案就是 ans+nn2,注意约分。

Code:Github CodeBase-of-Plozia P2634 [国家集训队]聪聪可可.cpp

P4149 [IOI2011]Race

考虑点分治。

emm如果你对点分治的套路足够熟悉的话这道题就是道裸题。

我们开一个桶 book,其中 booki 表示路径长度为 i 的路径经过边数的最小值。

然后拿 tmp 做类似的玩意,转移就好了。

Code:Github CodeBase-of-Plozia P4149 [IOI2011]Race.cpp

3. 总结

点分治的题目通常都带有路径统计的特点,其考点通常在 Solve 函数上,如何设计 Solve 函数是关键。

posted @   Plozia  阅读(24)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· Apache Tomcat RCE漏洞复现(CVE-2025-24813)
点击右上角即可分享
微信分享提示