【前缀和 + 双指针】第十三届蓝桥杯省赛C++ B组《统计子矩阵》(C++)

【题目描述】

给定一个 N×M 的矩阵 A,请你统计有多少个子矩阵 (最小 1×1,最大 N×M) 满足子矩阵中所有数的和不超过给定的整数 K?

【输入格式】

第一行包含三个整数 N,M 和 K。

之后 N 行每行包含 M 个整数,代表矩阵 A。

【输出格式】

一个整数代表答案。

【数据范围】

对于 30% 的数据,N,M≤20,

对于 70% 的数据,N,M≤100,

对于 100% 的数据,1≤N,M≤500;0≤Aij≤1000;1≤K≤2.5×10的8次方。

【输入样例】

3 4 10
1 2 3 4
5 6 7 8
9 10 11 12

【输出样例】

19

【样例解释】

满足条件的子矩阵一共有 19,包含:

  • 大小为 1×1 的有 10 个。
  • 大小为 1×2 的有 3 个。
  • 大小为 1×3 的有 2 个。
  • 大小为 1×4 的有 1 个。
  • 大小为 2×1 的有 3 个。

【代码】

cpp 复制代码
#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;

typedef long long LL;

const int N = 510;

int n, m, K;
int s[N][N];

int main()
{
    scanf("%d%d%d", &n, &m, &K);

    for (int i = 1; i <= n; i ++ )
        for (int j = 1; j <= m; j ++ )
        {
            scanf("%d", &s[i][j]);
            s[i][j] += s[i - 1][j];
        }

    LL res = 0;
    for (int i = 1; i <= n; i ++ )
        for (int j = i; j <= n; j ++ )
            for (int l = 1, r = 1, sum = 0; r <= m; r ++ )
            {
                sum += s[j][r] - s[i - 1][r];
                while (sum > K)
                {
                    sum -= s[j][l] - s[i - 1][l];
                    l ++ ;
                }
                res += r - l + 1;
            }

    printf("%lld\n", res);
    return 0;
}
相关推荐
可靠的仙人掌24 分钟前
SAC(Soft Actor-Critic)算法底座
开发语言·算法·php
王老师青少年编程1 小时前
csp信奥赛C++高频考点专项训练:【二分答案】案例2:木材加工
c++·二分答案·csp·高频考点·信奥赛·木材加工
海石2 小时前
单调栈复健,顺便,牺牲一下吧,空间复杂度!一切献给AC
算法·leetcode
海石2 小时前
JS击败94%,Hard题想不到动态规划,那就用数组和栈试试
算法·leetcode
aaPIXa6222 小时前
C++模板元编程:编译期计算Fibonacci数列
java·开发语言·c++
Augustzero2 小时前
`co_await` 按下暂停键之后:从零看懂 C++20 协程
c++·后端
知无不研3 小时前
c语言和c++中的静态关键字
开发语言·c++·静态关键字
思麟呀3 小时前
在C++基础上理解CSharp-7
java·jvm·c++·c#
2601_949818093 小时前
Vector从入门到应用(C++ STL动态数组万字全解
开发语言·c++
汉克老师4 小时前
GESP2026年6月认证C++八级( 第三部分编程题(1、线网建设))精讲
c++·最小生成树·排序·kruskal·并查集·gesp8级