同步发表于 P3755 题解。
0. 前置知识 & 废话
本蒟蒻最近学习 CDQ 分治,看到该题,虽然想起了扫描线等方法,但为了训练 CDQ 分治,还是自然写一篇题解。
本文是使用的三维偏序,如果不懂的话,可以A 这道题,想更多了解 CDQ 分治的,一波广告 我的 Blog。
1. 关于 CDQ 分治
CDQ 分治是一个离线分治算法,用于解决三维的问题。
它是在解决二维的基础上,再套一个树状数组来维护时间的先后顺序,复杂度比同类的二维问题多 $\log n$。
相信你 A 了模板题,会对这算法有更深的理解。
2. 关于本题
- 有 $n$ 个先给出的点,每一个点有一个权值,在给出 $m$ 个矩形边框,给出两个点 $(x_1,y_1),(x_2,y_2)$,求围住的点的总权值。
- $n\leq 10^5,m\leq 10^5,-2^{31}\leq x_1,x_2,y_1,y_2\leq 2^{31}$。
虽然近乎于一道模板题,直接扫描线,但是我们还是可以使用一下 CDQ 分治。
CDQ 分治的关键就在于构造一个三维偏序问题。
注意,有的题解使用的是二维偏序问题,我这里为了更加与模板吻合,构造了第三维,使用标准的三维偏序。
首先,我们可以将其转化为一个二维前缀和的问题,即 $ans=\operatorname{sum}(x_2,y_2)-\operatorname{sum}(x_1-1,y_2)-\operatorname{sum}(x_2,y_1-1)+\operatorname {sum}(x_1-1,y_1-1)$(就是一个容斥原理)。
于是,问题就是求
第一和第二维很简单,直接是 $x$ 和 $y$。
怎样求第三维呢?
可以发现,我们要构造为 $z<z_t$,又因为 CDQ 分治是离线,询问和答案在一起。
于是,我们可以用一个 $z$ 来标记是询问还是原来的点。
我们要加答案的是原来的点,而不是询问,所以我们将原来的点记为 0,询问记为 1。
那么,我们现在求的是:
于是就是一个标准的偏序问题了!
3. 关于 Code
- 我们需要使用 long long,因为很可能炸 int。
- 实际使用 $z$ 的时候,我们其实不需完全使用原来的三维偏序,其实可以将 $z=0$ 时加入总和即可。
然后就是愉快的上代码时间了!
1 |
|