点分治 cdq分治 整体二分 线段树分治 学习笔记
1、线段树分治
P5787 二分图 /【模板】线段树分治
首先考虑所有区间全部相离的情况。
这个时候可以直接用可撤销的并查集维护图中是否有奇环来解决。
再考虑有相离和互相包含两种情况。
其实和上面是差不多的,直接插入撤销判断奇环即可。
所以并没有什么好说的。
但是如果有相交?
我们的撤销只能按插入的顺序反着撤销,不能够颠倒顺序,否则是错的。
于是我们可以想到用LCT来维护联通性。(???)
不用LCT也可以。
我们考虑暴力,把每一个加边的区间拆掉,转化为第二种情况(相包含和相离)即可求解。
稍微优化一下暴力,不要拆到最小,利用时序线段树的区间,把每一个修改转化到线段树上的\(logn\)个节点即可解决问题。
这个时候每一个线段树节点上都会对应一些在这一整段上都存在的边。加入之后判断,往左右找,最后撤销即可。
P5227 [AHOI2013]连通图
az。直接转化为在某些时间加入边即可。判断任意一块并查集大小是否为n。
CF576E Painting Edges
k很小,可以暴力。
唯一不同的地方在于我们无法事先确定每一个操作是否执行。
那就线段树走到那个地方判断一下再加入即可。
考虑一次操作至少可以持续到下一次对这条边的操作,先在这一段加入这条边。如果下一次操作失败相当于把当前操作替换为上一次的操作然后继续加入图中。否则加入当前操作。
(在这之前先要撤销上一次操作)
2、点分治
其实并不是很难啦。多用于处理一些点对问题,路径问题。
P2634 [国家集训队]聪聪可可
考虑用f[0/1/2]统计当前扫过的子树(不包括当前这个)有多少个0 1 2长度路径。
扫完当前这一个再把当前这个子树贡献加入f。
其他跟距离相关问题都非常的裸。都是两种类似的方法:
第一种:跑出所有的点的贡献后排序。利用走指针的方式更新对于某一个i合法的区间j即可,然后减去当前这个子树的合法答案即可,这可以在走指针的同时维护。
第二种:类似上一道题,先统计再加入f数组。两次dfs(这样其实挺好写我感觉)。
最大的问题在于不要忘记只有自己一个子树连到根组成路径的情况
P4292 [WC2010]重建计划
真DIO一个题。
首先可以发现很明显的二分答案。
问题转化为求距离为\([L,R]\)的长度>=x的路径是否存在。
很简单,利用上述第二种维护方法,维护一个单调队列即可。即到当前根距离为[l,r]的点中到根最大距离的点。
可以发现,每一次点分治到一个新的重心,最大的deep会减小一半。最后均摊的时间复杂度是\(O(nlog^2n)\)的
但是直接交还过不去,会被卡常。因为每一次二分都要扫整棵树,考虑存一下每一次重心的位置,不要每次都扫整棵树来求重心,可以降低很多常数。
这其实就是点分树。
3、CDQ分治
算法李煜东讲得挺好的,秒懂。
主要注意一个非常非常坑的地方。
当某一位的两个元素相同的时候应该如!何!处!理!
在模板陌上花开中,我们可以发现完全相同元素根本无法被统计。所以只有拿出来单独考虑,把相同的压成一个。对于x相同或者x和y都相同的,我们要考虑z小的可能对后面一个z大的有贡献。所以我们排序的时候应该是三个关键字一起排序,否则可能会漏掉一些贡献。
在另一道题中,如果两个y相同,我们必须考虑先把在mid左边的相同y的元素全部处理完然后再统计右边答案。其实这种做法应该才是最普遍的,也是最不容易错的。
在排序的时候,尽量使用归并排序并使用上述第二种方法统计答案。
4、整体二分
李煜东讲得也挺好的
这个算法也并没有什么细节。该怎么做就怎么做。
本文来自博客园,作者:lei_yu,转载请注明原文链接:https://www.cnblogs.com/lytql/p/15354609.html

浙公网安备 33010602011771号