由于xi yi在0到5000之间,我们之前学的前缀和模板都是从下标1开始,我们就把x和y各自加1就好了,也就是在1到5001之间了,题目又说了,同一位置可能有多个目标,所以我们在一个位置求价值的时候应该用加等来求和
我们回顾一下之前构建前缀和数组的公式
公式应该是f[i][j]=f[i-1][j]+f[i][j-1]-f[i-1][j-1]+a[i][j]
之后我们要求炸毁的最大价值,就要枚举出所有变成为m的正方形,于是乎我们就可以从m,m这个坐标开始依次往后枚举,每次枚举的坐标是x2,y2 那么左上角的坐标就应该是 x2-m+1,y2-m+1
再结合我们之前学的求两点之间的矩形面积的公式
D=U-(A+B)-(A+C)+A 也就是D = f[x2][y2]-f[x1-1][y2]-f[x2][y1-1]+f[x1-1][y1-1]
好了,我们直接来写代码吧
#include <iostream>
using namespace std;
const int N = 5010;
int n, m;
typedef long long LL;
int a[N][N];
int f[N][N];
int main()
{
cin >> n >> m;
for (int i = 1; i <= n; i++)
{
int x, y, v; cin >> x >> y >> v;
x++, y++;
a[x][y] += v;
}
n = 5001;
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= n; j++)
{
f[i][j] = f[i - 1][j] + f[i][j - 1] - f[i - 1][j - 1] + a[i][j];
}
}
int ret = 0;
for (int x2 = m; x2 <= n; x2++)
{
for (int y2 = m; y2 <= n; y2++)
{
int x1 = x2 - m + 1, y1 = y2 - m + 1;
ret = max(ret, f[x2][y2] - f[x1 - 1][y2] - f[x2][y1 - 1] + f[x1 - 1][y1 - 1]);
}
}
cout << ret << endl;
return 0;
}