1 条题解
-
1琪露诺 (9Cirno) LV 8 MOD Baka 扶苏 tayz @ 2024-10-05 20:02:25
题意:
给定一个矩阵,定义两个子矩阵互为友矩阵当且仅当:
1. 权值和相等。
2. 左上角在同一个点。
3. 右下角不在同一个点。
4. 长加宽之和相等。
5. 长减宽之差互为相反数。
- 求给定矩阵上长为 a 宽为 b 的权值和最大的子矩阵的权值和。
- \(1 \leq n, m \leq 1000, 1 \leq a < n, 1 \leq b < m, \lvert Ai,j \rvert \leq 1919810\)。\(
S =
\begin{bmatrix}
a_{1, 1} & a_{1, 2} & \cdots & a_{1, n - 1} & a_{1, n} \\
a_{2, 1} & a_{2, 2} & \cdots & a_{2, n - 1} & a_{2, n} \\
\vdots & \vdots & \ddots & \vdots & \vdots \\
a_{m - 1, 1} & a_{m - 1, 2} & \cdots & a_{m - 1, n - 1} & a_{m - 1, n} \\
a_{m, 1} & a_{m, 2} & \cdots & a_{m, n - 1} & a_{m, n}
\end{bmatrix}
\)很明显,由条件 \(4\) 和条件 \(5\) 可得一个方程组:
\[
\begin{cases}
(r_{A, x} - l_{A, x}) + (r_{A, y} - l_{A, y}) = (r_{B, x} - l_{B, x}) + (r_{B, y} - l_{B, y}) \\
(r_{A, x} - l_{A, x}) - (r_{A, y} - l_{A, y}) + (r_{B, x} - l_{B, x}) - (r_{B, y} - l_{B, y}) = 0
\end{cases}
\]\[
解得:
\begin{cases}
r_{A, x} - l_{A, x} = r_{B, y} - l_{B, y} \\
r_{A, y} - l_{A, y} = r_{B, x} - l_{B, x}
\end{cases}
\]又因为\(
\begin{cases}
r_{A, x} - l_{A, x} = a\\
r_{A, y} - l_{A, y} = b
\end{cases}
\),于是,进一步我们可知 \(A\) 的长等于 \(B\) 的宽等于 \(a\),\(A\) 的宽等于 \(B\) 的长等于 \(b\);而又由于性质 \(2\),左上角的点被直接确定,因此对于每个矩阵,它可能的友矩阵都是唯一的。
即有:
\(
A = \begin{bmatrix}
a_{x_1. y_1} & \cdots & a_{x_1 + a - 1, y_1} \\
\vdots & \ddots & \vdots \\
a_{x_1, y_1 + b - 1} & \cdots & a_{x_1 + a - 1, y_1 + b - 1}
\end{bmatrix}
\)
\(
and
\)
\(
B = \begin{bmatrix}
a_{x_2. y_2} & \cdots & a_{x_2 + b - 1, y_2} \\
\vdots & \ddots & \vdots \\
a_{x_2, y_2 + a - 1} & \cdots & a_{x_2 + b - 1, y_2 + a - 1}
\end{bmatrix}
\)那我们又如何快速求矩阵的权值和呢?
我们想到使用二维前缀和,每次查询两个子矩阵的和是否相等即可,若相等则更新答案。
#include <iostream> using namespace std; typedef long long ll; ll read() { ll x = 0, f = 1; char ch = getchar(); for (; !isdigit(ch); ch = getchar()) if (ch == '-') f = -1; for (; isdigit(ch); ch = getchar()) x = (x << 1) + (x << 3) + (ch ^ 48); return x * f; } static const int N = 1010; ll pre[N][N]; ll get_sum(ll x, ll y, ll a, ll b) { return pre[x + a - 1][y + b - 1] - pre[x - 1][y + b - 1] - pre[x + a - 1][y - 1] + pre[x - 1][y - 1]; } int main() { ll n = read(), m = read(), a = read(), b = read(); for (int i = 1; i <= n; i++) for (int j = 1; j <= m; j++) { ll x = read(); pre[i][j] = x + pre[i - 1][j] + pre[i][j - 1] - pre[i - 1][j - 1]; } ll ans = -1145141919810; for (int i = 1; i + max(a, b) - 1 <= n; i++) for (int j = 1; j + max(a, b) - 1 <= m; j++) { ll suma = get_sum(i, j, a, b), sumb = get_sum(i, j, b, a); if (suma == sumb) ans = max(ans, suma); } if (ans == -1145141919810) cout << "Chinese_zjc_ L\n"; else cout << ans << '\n'; return 0; }
- 1