[luogu2280][bzoj1218][HNOI2003]激光炸弹

题目描述

一种新型的激光炸弹,可以摧毁一个边长为R的正方形内的所有的目标。现在地图上有n(N<=10000)个目标,用整数Xi,Yi(其值在[0,5000])表示目标在地图上的位置,每个目标都有一个价值。激光炸弹的投放是通过卫星定位的,但其有一个缺点,就是其爆破范围,即那个边长为R的正方形的边必须和x,y轴平行。若目标位于爆破正方形的边上,该目标将不会被摧毁。

解法

在题目描述中有这么一句话,若目标位于爆破正方形的边上,该目标将不会被摧毁。,这句话我觉得是一句废话,我们可以放在\(0.5\)这种位置。

今天做\(lyd\)的蓝皮做到的。首先如果考虑暴力,那么就是所有的点都枚举一遍,算出已这个节点为右下角的边长为\(R\)的正方形能够覆盖的节点的个数。

那么这个每个节点一定是要遍历的,我们考虑优化一下这个访问正方形中的权值。

非常容易想到,这是用二维的前缀和。

相当于我们要求答案\(ans[i][j]\),那么和\(ans[i][j]\)相关的某几块是\(sum[i-r][j]\)\(sum[i][j-r]\)\(sum[i-r][j-r]\)和。

根据容斥原理,\(ans[i][j]=sum[i][j]+sum[i-r][j-r]-sum[i-r][j]-sum[i][j-r]\)

ac代码

#include<bits/stdc++.h>
#define N 5001
using namespace std;
int read(){
    int w=0,x=0;char ch=0;
    while(!isdigit(ch))w|=ch=='-',ch=getchar();
    while(isdigit(ch))x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
    return w?-x:x;
}
int a[N+5][N+5];
int n,r;
int main(){
    n=read(),r=read();
    for(int i=1;i<=n;i++) a[read()+1][read()+1]=read();
    for(int i=1;i<=N;i++) for(int j=1;j<=N;j++) a[i][j]+=a[i-1][j];
    for(int i=1;i<=N;i++) for(int j=1;j<=N;j++) a[i][j]+=a[i][j-1];
    int ans=0;
    for(int i=r;i<=N;i++) for(int j=r;j<=N;j++) ans=max(ans,a[i][j]+a[i-r][j-r]-a[i-r][j]-a[i][j-r]);
    printf("%d\n",ans);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/chhokmah/p/10416892.html
今日推荐