码迷,mamicode.com
首页 > 编程语言 > 详细

[算法学习] 长链剖分

时间:2020-03-28 23:34:00      阅读:93      评论:0      收藏:0      [点我收藏+]

标签:for   ant   算法学习   ems   codeforce   dice   最大的   时间复杂度   长度   

简介

长链剖分是跟dsu on tree类似的小\(trick\),可以资瓷维护子树中只与深度有关的信息
并能达到线性的时间复杂度。

算法流程

对于每个点,记录重儿子\(heavy[u]\)表示深度最大的儿子,其余作为轻儿子
这样我们可以得到若干条互不相交的长链。
在维护信息的过程中,我们先\(O(1)\)继承重儿子的信息,再暴力合并其余轻儿子的信息。
因为每一个点属于一条长链,且一条长链只会在链顶位置作为轻儿子暴力合并一次,所以复杂度是线性的。
但是我们发现,这个数组仿佛开不下(大雾),所以我们需要想想办法来解决。
有一个比较巧妙的方法,就是利用指针来实现。
下面以一道题为例。

CF1009F Dominant Indices

题目链接:CF1009F Dominant Indices

Description

给定一个以 \(1\) 为根, \(n\) 个节点的树。
\(d(u,x)\)\(u\) 子树中到 \(u\) 距离为 \(x\) 的节点数。
求对于每一个点,最小的 \(k\) ,使得 \(d(u,k)\) 最大。
数据范围 \(1\le n\le 10^6\)

Solution

我们先考虑如何暴力做。
定义\(f_{u,i}\)表示在 \(u\) 的子树内,到 \(u\) 的距离为 \(i\) 的点的个数。
那么,我们不难推出转移方程: \(f_{u,0}=1,f_{u,i}=\sum_{v\in son(x)}f_{v,i-1}\)
复杂度:\(O(n^2)\),需要进行优化。
我们定义\(heavy[u]\)表示深度最大的儿子,\(len[u]\)表示\(x\)到儿子的最长距离。
不难发现\(dp\)第二维的 \(i\) 肯定不超过 \(len[u]\)
为避免数组存不下的问题,我们采用指针来代替,即对于每条长链的链顶给它一个长度为\(len[x]\)的内存。
这样的好处在于,对于一条长链,我们可以直接让父亲点从子节点那里继承答案。
对于非重儿子的点,我们暴力合并链即可。
很显然,每条链只会被合并一次,因此复杂度是线性的。
复杂度:\(O(n)\),可以通过本题。

Code

[算法学习] 长链剖分

标签:for   ant   算法学习   ems   codeforce   dice   最大的   时间复杂度   长度   

原文地址:https://www.cnblogs.com/wlzhouzhuan/p/12590088.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!