题目大意:
一个炸弹可以摧毁边长为
R
R
的正方形内的所有的目标。
地图上有个目标,用整数
Xi,Yi
X
i
,
Y
i
,表示位置,且都有一个价值
Zi
Z
i
。
炸弹的轰炸的那个边长为
R
R
的正方形的边必须和轴平行。且目标位于爆破正方形的边上,该目标将不会被摧毁。
N<=10000
N
<=
10000
Xi,Yi
X
i
,
Y
i
的数值在
[0,5000]
[
0
,
5000
]
分析:
这题很显然的就是二维前缀和,
可是因为边边的不算,那怎么办呢?
我们在边界延伸
0.5
0.5
的长度,
可以发现,这样就不会有边界的问题了,然后对
0.5
0.5
,
1.5
1.5
这样的坐标做一下前缀和就可以了
不过我们发现,这样特别麻烦,
然后我们可以知道,这样其实就是求一个允许点边长为
r
r
的正方形最多能覆盖的点的点权和最大是多少。
那么我们就可以用点去做二维前缀和。
时间复杂度:
然后我一开始找了一个
max(Xi),max(Yi)
m
a
x
(
X
i
)
,
m
a
x
(
Y
i
)
去做,
WA
W
A
了,
如果这样做,边界就需要取
max(
m
a
x
(
max(Xi),r)
m
a
x
(
X
i
)
,
r
)
,
max(
m
a
x
(
max(Yi),r)
m
a
x
(
Y
i
)
,
r
)
代码:
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#define N 5005
using namespace std;
int sum[N][N], maxx, maxy, ans, n, r;
int main()
{
scanf("%d %d", &n, &r);
int x, y, z;
for (int i = 1; i <= n; i++)
{
scanf("%d %d %d", &x, &y, &z);
++x, ++y;
maxx = max(maxx, x);
maxy = max(maxy, y);
sum[x][y] += z;
}
for (int i = 1; i <= max(maxx, r); i++)
for (int j = 1; j <= max(maxy, r); j++)
sum[i][j] = sum[i][j] + sum[i-1][j] + sum[i][j-1] - sum[i-1][j-1];
for (int i = r; i <= max(maxx, r); i++)
for (int j = r; j <= max(maxy, r); j++)
ans = max(ans, sum[i][j] - sum[i-r][j] - sum[i][j-r] + sum[i-r][j-r]);
printf("%d\n", ans);
return 0;
}