前缀和和差分(周灵猪)

二维前缀和

建图

preSum[i][j]=preSum[i−1][j]+preSum[i][j−1]−preSum[i−1][j−1]+matrix[i][j]

matrix[i][j]是这个位置的值

前提i,j是从1,1开始

for(int i=0;i<a;i++)

    {

        for(int i1=0;i1<b;i1++)

        {

            dp[i+1][i1+1]=dp[i+1][i1]+dp[i][i1+1]+mat[i][i1]-dp[i][i1];

        }

    }

这个就是从0,0开始建了

上面是建立

下面才是求

如果要求 [row1, col1][row1,col1] 到 [row2, col2][row2,col2] 的子矩形的面积的话,用 preSum 对应了以下的递推公式:

preSum[row2][col2] - preSum[row2][col1 - 1] - preSum[row1 - 1][col2] + preSum[row1 - 1][col1 - 1]
preSum[row2][col2]−preSum[row2][col1−1]−preSum[row1−1][col2]+preSum[row1−1][col1−1

F 统计子矩阵 (15分)
【问题描述】
给定一个 N × M N × MN×M 的矩阵 A AA,请你统计有多少个子矩阵(最小 1 × 1 1 × 11×1,最大 N × M N × MN×M) 满足子矩阵中所有数的和不超过给定的整数 K KK?

【输入格式】
第一行包含三个整数 N NN, M MM 和 K KK.
之后 N NN 行每行包含 M MM 个整数,代表矩阵 A AA.

【输出格式】
一个整数代表答案。

【样例输入】

3 4 10
1 2 3 4
5 6 7 8
9 10 11 12
1
2
3
4
【样例输出】

19
1
【样例说明】
满足条件的子矩阵一共有 19 1919,包含:
大小为 1 × 1 1 × 11×1 的有 10 1010 个。
大小为 1 × 2 1 × 21×2 的有 3 33 个。
大小为 1 × 3 1 × 31×3 的有 2 22 个。
大小为 1 × 4 1 × 41×4 的有 1 11 个。
大小为 2 × 1 2 × 12×1 的有 3 33 个。

【评测用例规模与约定】
对于 30 % 30\%30% 的数据,N , M ≤ 20 N, M ≤ 20N,M≤20.
对于 70 % 70\%70% 的数据,N , M ≤ 100 N, M ≤ 100N,M≤100.
对于 100 % 100\%100% 的数据,1 ≤ N , M ≤ 500 ; 0 ≤ A i j ≤ 1000 ; 1 ≤ K ≤ 250000000 1 ≤ N, M ≤ 500; 0 ≤ A_{ij} ≤ 1000; 1 ≤ K ≤ 2500000001≤N,M≤500;0≤A 
ij

 ≤1000;1≤K≤250000000.

题解
得 70 % 70\%70% 分的做法:前缀和 + n^4 枚举

#include <bits/stdc++.h>
#define ll long long
#define N 502
using namespace std;
int n, m, k;
int a[N][N], sum[N][N];
ll ans = 0;
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", &a[i][j]);
        }
    }
    for (int i = 1; i <= n; ++i) {
        for (int j = 1; j <= m; ++j) {
            sum[i][j] =
                a[i][j] + sum[i - 1][j] + sum[i][j - 1] - sum[i - 1][j - 1];
        }
    }
    for (int i = 1; i <= n; ++i) {
        for (int j = 1; j <= m; ++j) {
            for (int x = i; x <= n; ++x) {
                for (int y = j; y <= m; ++y) {
                    if (sum[x][y] - sum[x][j - 1] - sum[i - 1][y] +
                            sum[i - 1][j - 1] <=
                        k) {
                        ++ans;
                    }
                }
            }
        }
    }
    printf("%lld\n", ans);
    return 0;
}
————————————————
版权声明:本文为CSDN博主「weifeng2356」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_45799024/article/details/124059814

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值