神秘题 By qyc
qyc 讲题汇总。先讲我听懂的。
动态图连通性
题意简述
维护一张点数为 $n$ 的无向简单图,$m$ 次操作,加入或删除一条边及查询两个点是否连通。
$n\leq 5\times 10^3,m\leq 5\times 10^5$。
解法一:线段树分治(离线)
在时间轴上,每条边都有自己存在的时间段。我们在操作的时间轴上建立一棵线段树,每条边插入进其所完全包含的线段树上 $O(\log m)$ 个区间上。
在线段树上进行 DFS,同时维护一个表示连通块的并查集。这个并查集被要求是支持撤销操作的,为此我们使用按秩合并,每次修改时记录 fa
变化的那个点。每当我们进入一个线段树节点时,把节点里的所有边加入到并查集中,离开时撤销掉。当递归到叶子节点时计算询问。
容易证明这是正确的,因为当我们递归到叶子节点的时候,所有包含这一时间点的边都已经被加入到并查集中,同时撤销操作保证了没有包含这一节点的边不在并查集中。
分析一下时间复杂度。单个询问处理 $O(\log n)$,并查集合并 $O(\log n)$,撤销 $O(1)$。因为在线段树上,原来的 $O(m)$ 条边被拆分成了 $O(m\log m)$ 条边,每条边分别被合并撤销一次,所以是 $O(m\log n\log m)$ 的。
代码注意按秩合并别写假了,还有就是合并一条边时其可能已经被合并了,不能单单按照数量来进行撤销。
1 |
|
解法二:LCT(在线)
不会。
CF1442D Sum
题意简述
给定 $n$ 个不降的数组 $a_i$,你需要执行 $k$ 次操作:选择其中一个数组的首个元素并将其拿出来。最大化拿出来元素的和。
$\sum |a_i|\leq 10^6,n,k\leq 3\times 10^3$。
解法:线段树分治
注意到一个关键结论:如果你选了某个数组的元素,那么你要么把这个数组选完,要么因为剩余次数不够而选一个前缀。
所以可以把 $n$ 个数组看成 $n$ 个物品,费用是 $|a_i|$,价值是 $\sum a_i$。每次枚举没选完的那个数组,对剩下的数组做 $0/1$ 背包。但这样是 $O(nk^2)$ 的,显然过不了。
考虑到每次 $0/1$ 背包时,数据有很大一部分是重复的,所以我们考虑使用线段树分治来使数据利用最大化。
具体地,在 $1$ 到 $n$ 上建立线段树。进入一个节点时,从其父亲那继承背包的 DP 数组,把 $m+1$ 到 $r$ 的数组加入背包,向左递归,然后清空,把 $l$ 到 $m$ 的数组加入背包,向右递归。到达叶子节点时,除了这个节点的数组,其他的都已加入背包,所以直接枚举这个数组选了几个,跟背包的 DP 数组结合统计答案。正确性显然。
分析一下复杂度。把一个数组加入背包是 $O(k)$ 的。递归每一层都要加入 $n$ 个数组,一共有 $\log n$ 层,单个叶子节点统计答案复杂度是 $O(k)$ 的。所以总复杂度是 $O(nk\log n)$,可以通过。
1 |
|