(前缀和)激光炸弹

题目链接

根据题意画出格点,观察到到当正方形恰好和图形的边框重合时,设小正方形的边长为R,

那么此时圈中的点组成的方形的长度为(R-1)*(R-1),也就是(R - 1)* ( R - 1)个点,而假

如将大的方形稍微挪动一点到第二张图片所示位置,那么就能圈中R * R个点。

还有需要注意的一点就是由于题目给的正方形长度为1e9,而点的最大值为5000,所以需要

求出点的最大值并将其作为新的正方形的长和宽。

另外,本体主要是考察二维前缀和算法,对于二位前缀和,

假如有二维数组 a 以及二维前缀和数组 sum, 那么 sum[ i ] [ j ] = sum[ i - 1][ j ] + sum[ i ] [ j - 1] + a [ i ] [ j ] - sum[ i  - 1] [ j - 1]

 1 #include <iostream>
 2 #include <algorithm>
 3 #include <cstdio>
 4 using namespace std;
 5 int n, cnt, r, m;
 6 int sum[5010][5010];
 7 int main(){
 8     cin >> cnt >> r;
 9     int x, y, v;
10     r = min(5001, r);
11     n = m = r;
12     for (int i = 1; i <= cnt; i ++) {
13         scanf("%d %d %d", &x, &y, &v);
14         x++, y++;
15         n = max(n, x), m = max(m, y);
16         sum[x][y] += v;
17     }
18     for (int i = 1; i <= n; i ++){
19         for(int j = 1; j <= m; j ++){
20              sum[i][j] += sum[i - 1][j] + sum[i][j - 1] - sum[i - 1][j - 1];
21         }
22     }
23     int maxn = -1;
24     for(int i = r; i <= n; i ++){
25         for(int j = r; j <= m; j ++){
26             maxn = max(sum[i][j] - sum[i - r][j] - sum[i][j - r] + sum[i - r][j - r], maxn);
27         }
28     }
29     cout << maxn << endl;
30     return 0;
31 }
原文地址:https://www.cnblogs.com/pureayu/p/13559866.html