其他分享
首页 > 其他分享> > 图论专题-专项训练:点分治

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

作者:互联网

目录

1. 前言

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

前置知识:点分治算法。

2. 练习题

题单:

P4178 Tree

考虑点分治。

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

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

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

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

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

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

考虑点分治。

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

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

这样,总的点对个数是 \(n^2\),我们只需要统计路径长度为 3 的倍数的路径就好。

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

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

设当前子树统计结果是 \(tmp\),那么这棵子树对答案的贡献就是 \(2 \times (tmp_0 \times book_0 + tmp1 \times book_2 + tmp2 \times book_1)+2 \times tmp_0\)。

最后的答案就是 \(\dfrac{ans+n}{n^2}\),注意约分。

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

P4149 [IOI2011]Race

考虑点分治。

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

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

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

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

3. 总结

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

标签:tmp,图论,路径,分治,book,Solve,聪聪,专题
来源: https://www.cnblogs.com/Plozia/p/16156545.html