统计子矩阵

统计子矩阵

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

输入格式

第一行包含三个整数 N,MK

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

输出格式

一个整数代表答案。

数据范围

对于 30% 的数据,N,M20
对于 70% 的数据,N,M100
对于 100% 的数据,1N,M500;0Aij1000;1K2.5×108

输入样例:

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 个。

 

解题思路

  参考 [COCI2021-2022#6] Zemljište 中枚举子矩阵的方法,即枚举子矩阵的上边界、下边界、右边界,然后通过二分或双指针来确定左边界,这样时间复杂度就能做到 O(n3logn)O(n3)。记录这两题主要想告诉自己,枚举子矩阵不要总是那么死板去想着枚举左上角和右下角两个坐标。

  下面给出双指针做法的正确性证明就可以了。首先矩阵中的元素均是非负整数,因此当确定了子矩阵的上边界 x1,下边界 x2,右边界 y2 后,随着 y1 增加(向右移动),那么构成的矩阵 (x1,y1,x2,y2) 的和也会递减,因此满足单调性。假设此时左边界 y1 是满足构成矩阵和不超过 k 的最靠左的位置,那么当 y2 向右移动到 y2y1 只会向右移动。否则假设 y1 向左移动到 y1,由于矩阵 (x1,y1,x2,y2) 的和不超过 k,因此矩阵 (x1,y1,x2,y2) 的和也不超过 k,而 y1<y1,这就与假设矛盾了。

  AC 代码如下,时间复杂度为 O(n3)

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

const int N = 510;

typedef long long LL;

int s[N][N];

int main() {
    int n, m, k;
    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] + s[i][j - 1] - s[i - 1][j - 1];
        }
    }
    LL ret = 0;
    for (int i = 1; i <= n; i++) {
        for (int j = i; j <= n; j++) {
            for (int u = 1, v = 1; u <= m; u++) {
                while (v <= u && s[j][u] - s[i - 1][u] - s[j][v - 1] + s[i - 1][v - 1] > k) {
                    v++;
                }
                ret += u - v + 1;
            }
        }
    }
    printf("%lld", ret);
    
    return 0;
}

 

参考资料

  AcWing 4405. 统计子矩阵(秋招每日一题):https://www.acwing.com/video/4234/

posted @   onlyblues  阅读(49)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
Web Analytics
点击右上角即可分享
微信分享提示