线段树分治学习笔记
线段树分治是一种通过线段树维护时间轴,实现一些可撤销的信息维护问题的手段。
线段树分治是离线算法。
具体地,对于若干个修改与询问,按照时间戳像区间修改一样挂在线段树的节点上,然后遍历整棵线段树,将节点上的操作计入贡献,对于一个时间戳为 \(t\) 的询问,线段树上区间 \([t,t]\) 即为答案,在遍历完一个区间的左右儿子后,再将该节点操作撤销。这样就保证了对于时间 \(t\) 只有时间范围包含 \(t\) 的操作对答案有贡献。
首先对于二分图的判定,染色显然是不现实的,可以使用扩展域并查集解决,将一个点 \(x\) 拆为 \(x_1\) 和 \(x_2\),若连边时发现两个点 \(x_1\) 与 \(y_2\) 已经属于同一集合,则说明存在奇环,不是二分图。接下来使用线段树分治,将每条边挂在线段树上,当走到一个线段树上一个区间时,若将该区间上挂着的所有边都加入并查集后出现了奇环,那么说明该区间所有时间答案全部为 \(\text{No}\)。若已经走到叶子节点仍未出现矛盾,则说明该时间答案为 \(\text{Yes}\)。对于并查集的撤销,不进行路径压缩,保留树的形态,用一个栈记录一下最新修改的 \(fa\),在离开区间时将栈中节点 \(fa_i=i\),为了保证时间复杂度的正确,使用按秩合并即可。
同理,将修改看作建立另一条新边,同时删除旧的边,这样就又转化为了每条边有一定存在时限的问题,然后考虑怎样求出答案,参考 [WC2011] 最大XOR和路径,有贡献的边一定位于一个环上,那么就动态维护所有环的异或长度,插入线性基中,用栈记录新产生的环在线性基中是哪一位,最后退出时将该位清零即可。
本文来自博客园,作者:Aurora_Borealis,转载请注明原文链接:https://www.cnblogs.com/Aurora-Borealis-Not-Found/p/18295343