H. Hard Demon Problem
H. Hard Demon Problem
Swing is opening a pancake factory! A good pancake factory must be good at flattening things, so Swing is going to test his new equipment on 2D matrices.
Swing is given an $n \times n$ matrix $M$ containing positive integers. He has $q$ queries to ask you.
For each query, he gives you four integers $x_1$, $y_1$, $x_2$, $y_2$ and asks you to flatten the submatrix bounded by $(x_1, y_1)$ and $(x_2, y_2)$ into an array $A$. Formally, $A = [M_{(x1,y1)}, M_{(x1,y1+1)}, \ldots, M_{(x1,y2)}, M_{(x1+1,y1)}, M_{(x1+1,y1+1)}, \ldots, M_{(x2,y2)}]$.
The following image depicts the flattening of a submatrix bounded by the red dotted lines. The orange arrows denote the direction that the elements of the submatrix are appended to the back of $A$, and $A$ is shown at the bottom of the image.
Afterwards, he asks you for the value of $\sum_{i=1}^{|A|} A_i \cdot i$ (sum of $A_i \cdot i$ over all $i$).
Input
The first line contains an integer $t$ ($1 \leq t \leq 10^3$) — the number of test cases.
The first line of each test contains two integers $n$ and $q$ ($1 \leq n \leq 2000, 1 \leq q \leq 10^6$) — the length of $M$ and the number of queries.
The following $n$ lines contain $n$ integers each, the $i$'th of which contains $M_{(i,1)}, M_{(i,2)}, \ldots, M_{(i,n)}$ ($1 \leq M_{(i, j)} \leq 10^6$).
The following $q$ lines contain four integers $x_1$, $y_1$, $x_2$, and $y_2$ ($1 \leq x_1 \leq x_2 \leq n, 1 \leq y_1 \leq y_2 \leq n$) — the bounds of the query.
It is guaranteed that the sum of $n$ over all test cases does not exceed $2000$ and the sum of $q$ over all test cases does not exceed $10^6$.
Output
For each test case, output the results of the $q$ queries on a new line.
Example
Input
2
4 3
1 5 2 4
4 9 5 3
4 5 2 3
1 5 5 2
1 1 4 4
2 2 3 3
1 2 4 3
3 3
1 2 3
4 5 6
7 8 9
1 1 1 3
1 3 3 3
2 2 2 2
Output
500 42 168
14 42 5
Note
In the second query of the first test case, $A = [9, 5, 5, 2]$. Therefore, the sum is $1 \cdot 9 + 2 \cdot 5 + 3 \cdot 5 + 4 \cdot 2 = 42$.
解题思路
纯粹就是把累加转换成前缀和的表示形式然后推式子,关键是需要维护前缀和很多,且式子很复杂易推错。
先从简单的情况考虑,假设询问的是某一行,即 $x_1 = x_2 = i$,此时的结果为
$$
\begin{align*}
&\sum\limits_{j=y_1}^{y_2}{(j-y_1+1)a_{i,j}} \\
=& \, (1-y_1)\sum\limits_{j=y_1}^{y_2}{a_{i,j}} + \sum\limits_{j=y_1}^{y_2}{j \cdot a_{i,j}}
\end{align*}
$$
记 $\dot{r}_{i,j} = \sum\limits_{k=1}^{j}{a_{i,k}}$,$\ddot{r}_{i,j} = \sum\limits_{k=1}^{j}{k \cdot a_{i,k}}$,则有
$$
\begin{align*}
& \, (1-y_1)\sum\limits_{j=y_1}^{y_2}{a_{i,j}} + \sum\limits_{j=y_1}^{y_2}{j \cdot a_{i,j}} \\
=& \, (1-y_1)(\dot{r}_{i,y_2} - \dot{r}_{i,y_1-1}) + \ddot{r}_{i,y_2} - \ddot{r}_{i,y_1-1}
\end{align*}
$$
现在考虑询问多行的情况,对于每一行,其实只需在上述结果的基础上再加上 $(i-x_1)(y_2-y_1+1)\sum\limits_{j=y_1}^{y_2}{a_{i,j}}$,以保证该行每个元素乘以的系数是正确的。
$$
\begin{align*}
&\sum\limits_{i=x_1}^{x_2} (1-y_1)(\dot{r}_{i,y_2} - \dot{r}_{i,y_1-1}) + \ddot{r}_{i,y_2} - \ddot{r}_{i,y_1-1} + (i-x_1)(y_2-y_1+1)\sum\limits_{j=y_1}^{y_2}{a_{i,j}} \\
=& \sum\limits_{i=x_1}^{x_2} (1-y_1)(\dot{r}_{i,y_2} - \dot{r}_{i,y_1-1}) + \ddot{r}_{i,y_2} - \ddot{r}_{i,y_1-1} + (i-x_1)(y_2-y_1+1)(\dot{r}_{i,y_2} - \dot{r}_{i,y_1-1}) \\
=& \, (y_2-y_1+1)\sum\limits_{i=x_1}^{x_2}{i \cdot \dot{r}_{i,y_2} - i \cdot \dot{r}_{i,y_1-1}} \\ &+(1-y_1-x_1(y_2-y_1+1))\sum\limits_{i=x_1}^{x_2}{\dot{r}_{i,y_2} - \dot{r}_{i,y_1-1}} \\ &+ \sum\limits_{i=x_1}^{x_2}{\ddot{r}_{i,y_2} - \ddot{r}_{i,y_1-1}}
\end{align*}
$$
记 $\dot{c}_{i,j} = \sum\limits_{k=1}^{i}{\dot{r}_{k,j}}$,$\ddot{c}_{i,j} = \sum\limits_{k=1}^{i}{\ddot{r}_{k,j}}$,$\dddot{c}_{i,j} = \sum\limits_{k=1}^{i}{k \cdot\dot{r}_{k,j}}$,则有
$$
\begin{align*}
& \, (y_2-y_1+1)\sum\limits_{i=x_1}^{x_2}{i \cdot \dot{r}_{i,y_2} - i \cdot \dot{r}_{i,y_1-1}} \\ &+ (1-y_1-x_1(y_2-y_1+1))\sum\limits_{i=x_1}^{x_2}{\dot{r}_{i,y_2} - \dot{r}_{i,y_1-1}} \\ &+ \sum\limits_{i=x_1}^{x_2}{\ddot{r}_{i,y_2} - \ddot{r}_{i,y_1-1}} \\
=& \, (y_2-y_1+1)(\dddot{c}_{x_2,y_2} - \dddot{c}_{x_1-1,y_2} - (\dddot{c}_{x_2,y_1-1} - \dddot{c}_{x_1-1,y_1-1})) \\ &+ (1-y_1-x_1(y_2-y_1+1))(\dot{c}_{x_2,y_2} - \dot{c}_{x_1-1,y_2} - (\dot{c}_{x_2,y_1-1} - \dot{c}_{x_1-1,y_1-1})) \\ &+ \ddot{c}_{x_2,y_2} - \ddot{c}_{x_1-1,y_2} - (\ddot{c}_{x_2,y_1-1} - \ddot{c}_{x_1-1,y_1-1})
\end{align*}
$$
记 $f(c) = c_{x_2,y_2} - c_{x_1-1,y_2} - (c_{x_2,y_1-1} - c_{x_1-1,y_1-1})$,则有
$$
\begin{align*}
& \, (y_2-y_1+1)(\dddot{c}_{x_2,y_2} - \dddot{c}_{x_1-1,y_2} - (\dddot{c}_{x_2,y_1-1} - \dddot{c}_{x_1-1,y_1})) \\ &+ (1-y_1-x_1(y_2-y_1+1))(\dot{c}_{x_2,y_2} - \dot{c}_{x_1-1,y_2} - (\dot{c}_{x_2,y_1-1} - \dot{c}_{x_1-1,y_1})) \\ &+ \ddot{c}_{x_2,y_2} - \ddot{c}_{x_1-1,y_2} - (\ddot{c}_{x_2,y_1-1} - \ddot{c}_{x_1-1,y_1}) \\
=& \, (y_2-y_1+1)f(\dddot{c}) + (1-y_1-x_1(y_2-y_1+1))f(\dot{c}) + f(\ddot{c})
\end{align*}
$$
AC 代码如下,时间复杂度为 $O(n^2 + q)$:
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 2005;
LL r1[N][N], r2[N][N], c1[N][N], c2[N][N], c3[N][N];
void solve() {
int n, m;
cin >> n >> m;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
int x;
cin >> x;
r1[i][j] = r1[i][j - 1] + x;
r2[i][j] = r2[i][j - 1] + j * x;
}
}
for (int j = 1; j <= n; j++) {
for (int i = 1; i <= n; i++) {
c1[i][j] = c1[i - 1][j] + r1[i][j];
c2[i][j] = c2[i - 1][j] + r2[i][j];
c3[i][j] = c3[i - 1][j] + i * r1[i][j];
}
}
while (m--) {
int x1, y1, x2, y2;
cin >> x1 >> y1 >> x2 >> y2;
auto f = [&](LL c[][N]) {
return c[x2][y2] - c[x1 - 1][y2] - c[x2][y1 - 1] + c[x1 - 1][y1 - 1];
};
cout << (y2 - y1 + 1) * f(c3) + (1 - y1 - x1 * (y2 - y1 + 1)) * f(c1) + f(c2) << ' ';
}
cout << '\n';
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int t;
cin >> t;
while (t--) {
solve();
}
return 0;
}
参考资料
Codeforces Round 993 (Div. 4) Editorial:https://codeforces.com/blog/entry/137306
本文来自博客园,作者:onlyblues,转载请注明原文链接:https://www.cnblogs.com/onlyblues/p/18616401