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

30 篇文章 0 订阅

题目大意:

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

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 的正方形最多能覆盖的点的点权和最大是多少。
那么我们就可以用点去做二维前缀和。
时间复杂度:O(N2)
然后我一开始找了一个 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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值