用树状数组维护一个二维数组即可。和二维前缀和求法一样。
具体实现见代码:
#include <bits/stdc++.h>
using namespace std;
int m, n, x, y;
int a[1010][1010], sum[1010][1010];
int lowbit(int x) {
return x & -x;
}
void add(int x, int y, int k) {
for (int i = x; i <= m; i += lowbit(i)) {
for (int j = y; j <= n; j += lowbit(j)) {
sum[i][j] += k;
}
}
}
int getsum(int x, int y) {
int ans = 0;
for (int i = x; i; i -= lowbit(i)) {
for (int j = y; j; j -= lowbit(j)) {
ans += sum[i][j];
}
}
return ans;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int t;
cin >> t;
while (t--) {
memset(sum, 0, sizeof sum);
cin >> m >> n >> x >> y;
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= n; j++) {
cin >> a[i][j];
add(i, j, a[i][j]); // 维护二维数组
}
}
int ans = -1;
for (int i = x; i <= m; i++) {
for (int j = y; j <= n; j++) {
// 二维前缀和思想
ans = max(ans, getsum(i, j) - getsum(i, j - y) - getsum(i - x, j) + getsum(i - x, j - y));
}
}
cout << ans << endl;
}
return 0;
}