2025-辽宁-复赛-第二题, 积分(points)
CSP-XL 2025辽宁复赛真题-第二题,二维数组前缀和考点,个人认为约相当于GESP四级+,五级-,难度⭐⭐★☆☆。
CSP-XL 2025辽宁复赛真题-第二题, 积分(points)
题目要求

题目分析
解题思路
题意梳理
给定一个 的整数矩阵,每个格子有一个积分值。
再给出两个边长 和 ,要求分别找出所有边长为 的正方形区域与边长为 的正方形区域,计算它们内部积分之和,最终输出这两个“最大子正方形和”中的较大者。
若 或 大于矩阵行列尺寸,则对应尺寸无法形成合法正方形,跳过。核心思路——二维前缀和
- 预处理:
构造二维前缀和数组pre_sum[i][j],表示从左上角 到 子矩阵的积分和。
递推式:pre_sum[i][j] = pre_sum[i-1][j] + pre_sum[i][j-1] - pre_sum[i-1][j-1] + a_array[i][j]
这样可在 时间内算出任意子正方形和。 - 枚举:
分别用两重循环枚举所有可能的左上角 ,若i+k-1≤n且j+k-1≤m( 取 或 ),则用前缀和公式sum = pre_sum[i+k-1][j+k-1] - pre_sum[i-1][j+k-1] - pre_sum[i+k-1][j-1] + pre_sum[i-1][j-1]
得到当前正方形积分,更新对应尺寸的最大值。 - 结果:
最终取max(max_x, max_y)输出即可。
- 预处理:
复杂度分析
- 时间:
预处理前缀和 ;
枚举所有 正方形最多 个, 同理,总体仍为 。 - 空间:
两个 的long long数组,约 。
- 时间:
边界与细节
- 当 或 大于 或 时,对应尺寸无法形成合法正方形,循环内提前
break减少无效枚举。 - 初始化最大值用
LLONG_MIN防止全负矩阵出错。 - 使用
freopen按复赛要求读写文件,行列下标统一从 1 开始,避免越界。
- 当 或 大于 或 时,对应尺寸无法形成合法正方形,循环内提前
示例代码
#include <algorithm>
#include <climits>
#include <iostream>
long long a_array[1005][1005]; // 存放原始二维数组,行列下标从1开始
long long pre_sum[1005][1005]; // 二维前缀和数组,pre_sum[i][j]表示(1,1)到(i,j)子矩阵的和
int main() {
freopen("points.in", "r", stdin); // 复赛标准输入文件
freopen("points.out", "w", stdout); // 复赛标准输出文件
int n, m, x, y; // n行m列,x×x与y×y两种尺寸的正方形区域
std::cin >> n >> m >> x >> y;
// 读入原始矩阵
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
std::cin >> a_array[i][j];
}
}
// 计算二维前缀和
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
pre_sum[i][j] = pre_sum[i - 1][j] + pre_sum[i][j - 1] -
pre_sum[i - 1][j - 1] + a_array[i][j];
}
}
// 枚举所有x×x正方形区域,求最大积分
long long max_x_points = LLONG_MIN; // 初始化为最小值
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
if (i + x - 1 <= n && j + x - 1 <= m) {
long long cur_points =
pre_sum[i + x - 1][j + x - 1] - pre_sum[i - 1][j + x - 1] -
pre_sum[i + x - 1][j - 1] + pre_sum[i - 1][j - 1];
max_x_points = std::max(max_x_points, cur_points);
} else {
break; // 当前行剩余位置无法满足x×x区域,直接跳出内层循环
}
}
}
// 枚举所有y×y正方形区域,求最大积分
long long max_y_points = LLONG_MIN;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
if (i + y - 1 <= n && j + y - 1 <= m) {
long long cur_points =
pre_sum[i + y - 1][j + y - 1] - pre_sum[i - 1][j + y - 1] -
pre_sum[i + y - 1][j - 1] + pre_sum[i - 1][j - 1];
max_y_points = std::max(max_y_points, cur_points);
} else {
break; // 同理,提前结束本行后续枚举
}
}
}
// 输出两种尺寸中的最大积分
long long max_points = std::max(max_x_points, max_y_points);
std::cout << max_points << std::endl;
return 0;
}附:样例和测试数据下载地址:
链接:https://pan.quark.cn/s/79e0531a87ed?pwd=1bK8 提取码:1bK8
本文由coderli.com原创,按照CC BY-NC-SA 4.0 进行授权
所有代码已上传至Github:https://github.com/lihongzheshuai/yummy-code
“luogu-”系列题目可在 洛谷题库 在线评测。
“bcqm-”系列题目可在 编程启蒙题库 在线评测。
GESP/CSP认证交流QQ群: 688906745
GESP/CSP 认证学习微信公众号

最后更新于