洛谷 P2280:[HNOI2003] 激光炸弹 ← 二维前缀和

​【题目来源】
https://www.luogu.com.cn/problem/P2280
https://www.acwing.com/problem/content/101/

【题目描述】
一种新型的激光炸弹,可以摧毁一个边长为 m 的正方形内的所有目标。
现在地图上有 n 个目标,用整数 xi, yi 表示目标在地图上的位置,每个目标都有一个价值 vi。
激光炸弹的投放是通过卫星定位的,但其有一个缺点,就是其爆破范围,即那个边长为 m 的边必须与 x 轴,y 轴平行。若目标位于爆破正方形的边上,该目标不会被摧毁。
现在你的任务是计算一颗炸弹最多能炸掉地图上总价值为多少的目标。
可能存在多个目标在同一位置上的情况。

【输入格式】
输入的第一行为整数 n 和整数 m;
接下来的 n 行,每行有 3 个整数 x,y,v,表示一个目标的坐标与价值。

【输出格式】
输出仅有一个正整数,表示一颗炸弹最多能炸掉地图上总价值为多少的目标(结果不会超过 32767 )。

【输入样例】
2 1
0 0 1
1 1 1

【输出样例】
1

【数据范围】
对于 100% 的数据,保证 1≤n≤10^4,0≤xi,yi≤5×10^3,1≤m≤5×10^3,1≤vi<100。

【算法分析】
二维前缀和两种构造方式(下标 i、j 从 1 开始):
(1)双数组版
先读入原数组:cin>>a[i][j];
再求前缀和:s[i][j]=s[i-1][j]+s[i][j-1]-s[i-1][j-1]+a[i][j];
数组 s 存前缀和,数组 a 存原始数据。
(2)单数组版
直接读入原始权值:cin>>s[i][j];
原地递推更新:s[i][j]+=s[i-1][j]+s[i][j-1]-s[i-1][j-1];
数组 s 初始存储原矩阵权值,经递推计算后原地覆盖,保存二维前缀和。

【算法代码】

#include <bits/stdc++.h>
using namespace std;

const int N=5e3+5;
const int lim=5e3+1;
int s[N][N];

int main() {
    int n,m;
    cin>>n>>m;
    for(int i=1; i<=n; i++) {
        int x,y,v;
        cin>>x>>y>>v;
        s[x+1][y+1]+=v;
    }

    for(int i=1; i<=lim; i++)
        for(int j=1; j<=lim; j++)
            s[i][j]+=s[i-1][j]+s[i][j-1]-s[i-1][j-1];

    int ans=0;
    for(int i=m; i<=lim; i++) {
        for(int j=m; j<=lim; j++) {
            int sum=s[i][j]-s[i-m][j]-s[i][j-m]+s[i-m][j-m];
            ans=max(ans,sum);
        }
    }
    cout<<ans<<endl;
    return 0;
}

/*
in:
2 1
0 0 1
1 1 1

out:
1
*/



【参考文献】
https://blog.csdn.net/hnjzsyjyj/article/details/145290457
https://blog.csdn.net/hnjzsyjyj/article/details/144918838
https://www.luogu.com.cn/problem/solution/P2280

 

​

posted @ 2026-11-10 19:44  Triwa  阅读(2)  评论(0)    收藏  举报