SHU20thSC 逃离魔爪
逃离魔爪
题目描述
安全穿过了雷区,你居然发现了一片农场,此时农场上十分热闹。
AuMiner
正在追捕一位在 QQ
农场偷菜的小偷 xyx
,好不容易马上就要抓到 xyx
了,xyx
突然回头求饶不要抓我,AuMiner
回应道可以不抓你但是你必须回答我的一系列问题,小偷 xyx
紧张极了,你能帮助小偷 xyx
逃离 AuMiner
的魔爪吗?
Auminer
有一块 $n \times m$ 的矩形地块,一开始,里面所有的格子都写着 $0$,代表所有地都未锄好,而 $1$ 代表地已经锄好。
AuMiner
会有以下的操作和询问:
- $1, x_1, y_1, x_2, y_2$, $(1 \leq x_1 \leq x_2 \leq n,1 \leq y1 \leq y_2 \leq m)$ 表示对
QQ
农场矩形范围左上角 $(x_1, y_1)$ 到右下角 $(x_2, y_2)$ 进行锄地,写有 $0$ 的田地会变成 $1$,写有 $1$ 的田地会变成 $0$。 - $2, x_1, y_1, x_2, y_2$, $(1 \leq x_1 \leq x_2 \leq n,1 \leq y1 \leq y_2 \leq m)$ 表示询问
QQ
农场的矩形范围左上角 $(x_1, y_1)$ 到右下角 $(x_2, y_2)$ 中锄好的地的数量的奇偶值。
数据样例
输入
1 | 2 2 |
输出
1 | 1 |
二维树状数组 - $O(Q * log^2(N))$
题目的含义
给定一个二维 $01$ 矩阵,有 $q$ 次询问,每次询问给定一个矩阵 $(x_1, y_1, x_2, y_2)$ 表示矩阵左上角和右下角点分别为 $(x_1, y_1), (x_2, y_2)$:
- $q = 1$:将当前矩阵中的所有 $01$ 进行翻转
- $q = 2$:询问当前矩阵中 $1$ 的个数是奇数还是偶数
转换矩阵差分
首先,对 $01$ 矩阵翻转,可以直接将矩阵所有的值 $+1$ 即可,利用奇偶性判断 $01$,那么对一个矩阵同时加一个数,可以利用二维差分进行维护。记差分数组为 $w$
那么现在产生一个问题是:虽然利用差分可以维护每次修改后的矩阵的状态,那么对于每次询问矩阵的和,如果用差分维护的话,那么如何才能维护前缀和呢?
$PS:$ 这个题目还有一个一维版本,如果对一维版本理解的话,那么这个题目会好理解很多
二维前缀和表示
我们来分析一下如何用矩阵差分 $w$ 表示二维前缀和,我们要表示二维前缀和是矩阵 $(1, 1, x, y)$ 中所有元素的和,首先我们依次看这个矩阵中的每个点如何表示:
- $(1, 1): w_{1, 1}$
- $(1, 2): w_{1, 1} + w_{1, 2}$
- $…$
- $(2, 1): w_{1, 1} + w_{2, 1}$
- $…$
将上面所有点对应的值全部加起来就是二维前缀和,那么我们可以观察每个 $w_{i, j}$ 被计算的次数:
- $w_{1, 1}$: 矩阵中所有点的计算都包含,因此一共计算 $x * y$ 次 - 矩阵 $(1, 1, x, y)$ 一共有 $x * y$ 个点
- $w_{1, 2}$: 所有在矩阵 $(1, 2, x, y)$ 中的点的值的计算都包括当前点,因此会计算 $x * (y - 1)$ 次
- $…$
因此我们观察发现 $w_{i, j}$ 被计算的点是矩阵 $(i, j, x, y)$ 中的所有点,因此:
$w_{i, j}$ 被计算的次数是:$(x - i + 1) * (y - j + 1)$
那么现在我们可以表示二维前缀和了:
$$S_{x, y} = \sum_{i = 1} ^ n \sum_{j = 1} ^ m w_{i, j} * (x - i + 1) * (y - j + 1)$$
树状数组维护前缀和
我们知道上述式子是无法直接维护的,因为 $x, y$ 的值每次都是不一样的,因此需要对上述式子进行等价变换,我们记:$w_{i, j}$ 为 $w$:
$$\begin{aligned}
S_{x, y} & = \sum_{i = 1} ^ n \sum_{j = 1} ^ m w * (x - i + 1) * (y - j + 1) \\
& = \sum_{i = 1} ^ n \sum_{j = 1} ^ m (w * (x + 1) - w * i) * (y - j + 1) \\
& = \sum_{i = 1} ^ n \sum_{j = 1} ^ m (w * (x + 1) * (y + 1) - w * j * (x + 1) - w * i * (y + 1) + w * i * j) \\
\end{aligned}$$
此时,我们就可以维护这个式子了,利用 $4$ 个二维树状数组分为维护:$w$, $w * i$, $w * j$, $w * i * j$ 即可
时间复杂度
二维树状数组每次修改和查询的复杂度都是 $O(log^2(N))$,一共 $Q$ 次查询,因此复杂度是:$O(Q * log^2(N))$
AC代码
1 |
|