Bzoj P1218 [HNOI2003]激光炸弹___二维前缀和

题目大意:

一个炸弹可以摧毁边长为 R 的正方形内的所有的目标。
地图上有 N 个目标,用整数 X i , Y i ,表示位置,且都有一个价值 Z i
炸弹的轰炸的那个边长为 R 的正方形的边必须和 x y 轴平行。且目标位于爆破正方形的边上,该目标将不会被摧毁。

N <= 10000
X i , Y i 的数值在 [ 0 , 5000 ]

分析:

这题很显然的就是二维前缀和,
可是因为边边的不算,那怎么办呢?
我们在边界延伸 0.5 的长度,
可以发现,这样就不会有边界的问题了,然后对 0.5 1.5 这样的坐标做一下前缀和就可以了
不过我们发现,这样特别麻烦,
然后我们可以知道,这样其实就是求一个允许点边长为 r 的正方形最多能覆盖的点的点权和最大是多少。
那么我们就可以用点去做二维前缀和。
时间复杂度: O ( N 2 )
然后我一开始找了一个 m a x ( X i ) , m a x ( Y i ) 去做, W A 了,
如果这样做,边界就需要取 m a x m a x ( X i ) r m a x 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;
}

猜你喜欢

转载自blog.csdn.net/Gx_Man_VIP/article/details/81304932