矩形面积并

矩形面积并

这个东西其实有一些说道的。。。扫描线之后变成:维护序列,支持

  • 区间 \(+1\),区间 \(-1\)
  • 查询全局 \(>0\) 的位置个数

这个东西乍一看,其实只能分块,维护每块排序的结果,套个二分做到 \(O(n\sqrt{n\log n})\)

但注意本题操作特殊,题目实际上保证了:任意时刻序列的每个位置均 \(\ge 0\)

那么只需要维护区间最小值与区间最小值的个数就可以正常下传标记了。显然答案也可以通过这两个值推出来。

许多题解提到了不维护懒标记的做法,这种做法是在对线段树的某个节点 \(p\) 修改的时候分类:

  • 如果是 \(+1\),直接令 \(ans_p\leftarrow r_p-l_p+1\),其中 \(ans,l,r\) 分别表示该节点所代表的区间中 \(>0\) 的位置个数与区间的左右端点。同时维护该区间整体被打标记的次数 \(c_p\),令 \(c_p\leftarrow c_p+1\)
  • 如果是 \(-1\),先令 \(c_p\leftarrow c_p-1\),若此时 \(c_p>0\) 那么 \(ans_p\) 仍为 \(r_p-l_p+1\),否则直接令 \(ans_p\leftarrow ans_{\text{lson}(p)}+ans_{\text{rson}(p)}\)

注意 \(c_p\) 并非懒标记,不需要做下传操作。

由于加法标记具有交换律,以及操作的特殊性质:每个区间 \([l,r]\) 恰好会被 \(+1\) 一次,\(-1\) 一次(这个性质使得线段树上的每个节点的加减一定成对出现),这个做法也是正确的。

我尝试解释一下:考虑节点 \(p\) 及其代表的区间 \([l_p,r_p]\),考虑所有与 \([l_p,r_p]\) 相交的修改区间 \([L,R]\)

  • \([l_p,r_p]\subseteq [L,R]\),那么我们成功计算了这次修改对 \([l_p,r_p]\) 的贡献。(但并没有计算这次修改对 \(p\) 子树中区间的贡献)
  • 否则,我们将 \([L,R]\) 拆成 \(O(\log n)\) 段区间后,考虑那些在 \(p\) 子树内的小区间,那么这次修改对这些区间的贡献也已经成功计算。实际上这次修改对 \([l_p,r_p]\) 仍然有贡献,但如果此时 \(c_p>0\),我们相当于忽略了这部分贡献(在这种情况下这部分贡献也是完全可以忽略的),当 \(c_p=0\) 时需要重新计算这部分贡献。
  • \(c_p\) 重新变为 \(0\) 时,这意味着 \(p\) 节点上的修改已经不会对子树内节点造成影响,第一种情况的所有修改已经相互抵消。那么此时 \(p\) 子树内的所有节点实际上已经算入了它们应该计算的所有贡献,因此只需要把这些贡献累加到 \(p\) 上即可,即 \(ans_p\leftarrow ans_{\text{lson}(p)}+ans_{\text{rson}(p)}\)

为什么我说这个是因为交换律呢,因为考虑 \(p\) 子树内的节点,如果 \(p\) 经历了 \(+A\),然后 \(-A\),那么子树内的节点实际上应该经历 \(+A,+B,-A\)。由于交换律的原因这等价于 \(+B,+A,-A\) 也就是 \(+B\),所以可以直接忽略 \(p\) 在前面的修改。

当然作者比较菜 QAQ,理解的也比较浅薄,如果哪位好心鸽鸽有更好的理解请告诉我/可怜

posted @ 2023-01-05 18:04  云浅知处  阅读(99)  评论(0编辑  收藏  举报