首页 > 其他分享 >线段树分治&可撤销并查集

线段树分治&可撤销并查集

时间:2023-09-28 14:56:33浏览次数:37  
标签:连通 查集 线段 分治 撤销 答案

可撤销并查集

按时间顺序用一个栈维护合并信息,撤销时从栈顶弹出合并信息,恢复原状态。

并查集查找祖先时 不能路径压缩,只能按秩合并

例题:

[ABC302Ex] Ball Collector

容易想到将 \(A_i\) 和 \(B_i\) 之间连边。

遍历整棵树,用可撤销并查集维护图。

为了进一步求得答案,需要注意到该结论:对于一个连通块,对当前答案的贡献为 \(\min(\text{点数}, \text{边数})\)。([ARC111B] Reversible Cards

证明可以考虑从树的特殊情况出发,添加一条返祖边,分析贡献的变化。

于是简单地维护这两个量和答案即可。

Warning:在实现上的注意:

之前写可撤销并查集时只用栈维护了合并两个连通块时的操作(由于不是路径压缩,因此父亲在一段时间内是固定的,你甚至可以只记录大小较小的连通块的祖先编号),并没有把每一步操作都记录下来,这是因为我们需要的信息只与连通块内的点有关,因此不需要知道连通块内连接的具体形态。但在这道题里,我们需要查询边的信息,因此需要把每一步操作都存进栈里。

线段树分治

xht 的题解对该算法的叙述精辟而清晰:

考虑这样一个问题:

  • 有一些操作,每个操作只在 \(l \sim r\) 的时间段内有效。
  • 有一些询问,每个询问某一个时间点所有操作的贡献。

对于这样的询问,我们可以离线后在时间轴上建一棵线段树,这样对于每个操作,相当于在线段树上进行区间操作。

遍历整颗线段树,到达每个节点时执行相应的操作,然后继续向下递归,到达叶子节点时统计贡献,回溯时撤销操作即可。

这样的思想被称为线段树分治,可以在低时间复杂度内解决一类在线算法并不优秀的问题。

例题:(没放板题)

线段树分治与可撤销并查集

P5631 最小mex生成树

枚举答案 \(x\),将所有权值为 \(x\) 的边删除,若剩下的边能够形成生成树(即图联通),说明原图上至少存在一棵生成树的 \(mex\) 值 \(\le x\),即答案 \(\le x\)。则最小使图连通的 \(x\) 即为答案。

将边权视作时间进行分治。将边权为 \(x\) 的出现时段分成 \([0, x - 1]\) 和 \([x + 1, \infin]\),最小使图连通的时间点即为答案。

空间复杂度 \(O(m\log{w})\),时间复杂度 \(O(m\log{n}\log{w})\)。(?

CF1681F Unique Occurrences

有了上面那道题的经验,这里仍然考虑 将边权视作时间进行分治

对于颜色 \(c\),将所有权值为 \(c\) 的边删除后形成若干连通块,原树上权值为 \(c\) 的边 \(x\) 所连的两个连通块的乘积即为通过 \(x\) 做出的贡献。

CF1140F Extending Set of Points

难得独立做出来 *2600。按时间分治,关键是如何维护答案。

经典套路,将二维平面上的点 \((x, y)\) 视作 \(x\) 与 \(y + N\) 之间连无向边,则答案为所有连通块内横坐标点数与纵坐标点数的乘积之和。

由于递归到叶子节点时统计答案的时间复杂度过高,可以 在并查集的合并与撤销时维护答案

[ABC163F] path pass i

将点权视作时间进行分治,用线段树分治维护连通块信息。

如果按原题意操作,发现线段树递归到叶子节点时不方便统计答案,因此可以容斥一下,去求不包含颜色 \(c\) 的路径数 \(cnt\)。

去掉所有端点权值为 \(c\) 的边,每个大小为 \(x\) 的连通块内对 \(cnt\) 贡献 \(\binom{x}{2} + x\)(注意此题中单点也算一条路径),但是切掉边后形成的颜色为 \(c\) 的单点不会做贡献,因此算的时候要把这部分去掉。

仍然是在并查集合并和撤销的过程中维护答案。

时间复杂度 \(O(n\log^{2}{n})\),但此题有线性做法。

标签:连通,查集,线段,分治,撤销,答案
From: https://www.cnblogs.com/Schucking-Sattin/p/17735787.html

相关文章

  • 根据一个数组,创建一个Segment Tree(线段树)
    线段树的特点线段树的优势线段树的构造过程(0,5)37:数组元素下标0~5的元素之和是37(0,2)21:数组元素下标0~2的元素之和是21线段树的基本数据结构(结点结构由五个分量组成)运行结果(C语言代码)递归的创建一颗线段树,然后中序、先序、后序遍历这个结点#include<stdio.h>#include<st......
  • 线段树复习
    1.楼房重建经典题。先转化题意,将斜率转化为每个点的权值,发现答案是单调递增的。那么就是求单点修改的最长上升子序列。用线段树维护两个信息当前区间的最大值mx,当前区间最长上升子序列长度len。修改时单点修改即可,考虑如何合并两个区间的len。可以在线段树上二分。get(o,k)......
  • 2023湖南省赛 E.ytree (线段树)
    传送门大致思路:1.将操作1拆分为两个部分x(-1)^d+kd(-1)^d。对于操作1中的x(-1)^d部分而言。我们可以对式子进行拆分,把x拆出来,我们会发现和v号点距离为奇数的点会减去x,为偶数的点会加上x,所以我们可以在线段树上用一个sum1维护应该减去的值,sum2维护加上的值即可。2.随即就是......
  • 分治算法
    基本思想:将序列分为\([l,mid]\)和\([mid+1,r]\),然后递归两边,同时再计算\([l,mid]\)与\([mid+1,r]\)影响所产生的答案(满足单调性的话一般使用走指针)。二维偏序首先将所有元素按\(x,y\)排序。然后递归两边,随后用两个指针\(i\)和\(j\),\(i\)从\(l\)到\(mid\),\(j\)......
  • <学习笔记>线段树分治
    一种离线处理方法可以处理“具体哪个修改对询问有影响”、可以贡献不独立、可以支持插入删除。例题对这道题来说,对修改开线段树,线段树上每个节点开一个\(vector\)来维护出现在这段区间的线段,加入一个线段的区间,直接在区间查询时对所包含的节点压入这条线段就可以。然后从根......
  • 【边分治】P4565 [CTSC2018] 暴力写挂
    初涉边分治。大致就是按照一条边的两端来分类出两套点,然后对这个进行分治,有点是只用考虑两类集合,考虑贡献很简单!!反正就是比点分强。但是如果直接分治是假的,会被菊花图薄纱,需要进行对树的三度化,这个是左儿子右兄弟,但是貌似很少人叫这个,比较不适,然后我们就可以做了。建出来的边分......
  • 线段树合并的复杂度
    线段树合并的时间复杂度是\(O(m\logn)\)的(\(m\)为插入次数)。intmer(intx,inty){if(!x||!y)returnx^y;t[x]+=t[y];returnL[x]=mer(L[x],L[y]),R[x]=mer(R[x],R[y]),x;}因为每个点只会在自己被删除(情况1)或父亲被删除且自己未删除的(即合并时另一个子树为空,......
  • 简单分治快排问题解析(c++实现)
    这几天刷了需要使用分治快排思想去解决的几道比较好的题目,所以写下这篇博客用于复习和以后的复盘。什么是分治快排思想首先我们要知道什么是分治快排思想,这个思想其实就是在模拟实现qsort算法的时候使用的一个方法,在模拟实现qsort的时候,我们知道第一步是需要使用一个随意选择(三数取......
  • 【学习笔记】(26) cdq 分治 与 整体二分
    cdq分治基本思想我们要解决一系列问题,这些问题一般包含修改和查询操作,可以把这些问题排成一个序列,用一个区间[L,R]表示。分。递归处理左边区间\([L,M]\)和右边区间\([M+1,R]\)的问题。治。合并两个子问题,同时考虑到\([L,M]\)内的修改对\([M+1,R]\)内的查询产生的影......
  • 【线段树合并、虚树】P5327 [ZJOI2019] 语言
    终于1kAC了家人,感动吧。贺了很久,很累。前置题目:P3320[SDOI2015]寻宝游戏虚树的边权和:\[\sumdep_{a_x}-\sum_{x<n}dep_{a_x,a_{x+1}}-dep_{a_{1},a_{n}}\]考虑转化贡献,求过该点的链的并,最后再除以二即可。那么我们可以考虑维护以该点的子树的所有关键点以及......