蓝桥杯——统计子矩阵


解法:二维前缀和+双指针

代码:

c 复制代码
#include <iostream>
using namespace std;
typedef long long ll;
ll prefix[505][505], a[250010];
int main()
{
	ll n, m, k, ans = 0; cin >> n >> m >> k;
  for(int i = 1; i <= n; i++)
     for(int j = 1; j <= m; j++){
       cin >> prefix[i][j];
       prefix[i][j] += prefix[i-1][j] + prefix[i][j-1] - prefix[i-1][j-1];
       //cout << prefix[i][j] << endl;
     }
  //for(int i = 1; i < n*m; i++) cout << prefix[i] << endl; 
  for(int i = 1; i <= n; i++)
    for(int j = 1; j <= i; j++){
      for(int l = 1, r = 1; r <= m; r++){
        while(l <= r && prefix[i][r] - prefix[i][l-1] - prefix[j-1][r] + prefix[j-1][l-1] > k) l++;
        if(l <= r) ans += r-l+1; //每一次循环,以r为区间,r每次必++
      }
    }
      
  cout << ans;
  return 0;
}

代码解释:

这段代码的核心是计算满足条件的子矩阵的数量。让我们逐步分析代码的逻辑,特别是你提到的 if (l <= r) ans += r - l + 1; 这一行。

代码逻辑概述

  1. 二维前缀和数组

    • prefix[i][j] 表示从矩阵的左上角 (1,1) 到当前位置 (i,j) 的子矩阵的元素和。
    • 通过二维前缀和,可以在常数时间内计算任意子矩阵的和。
  2. 目标

    • 找出所有满足条件的子矩阵数量,其中子矩阵的和不超过给定的阈值 k

关键代码分析

外层循环
cpp 复制代码
for (int i = 1; i <= n; i++) // 枚举子矩阵的上边界
    for (int j = i; j <= n; j++) // 枚举子矩阵的下边界
  • 这两层循环枚举了所有可能的子矩阵的上下边界。i 是子矩阵的上边界,j 是子矩阵的下边界。
内层循环
cpp 复制代码
for (int l = 1, r = 1; r <= m; r++) // 枚举子矩阵的右边界
  • 这一层循环枚举了子矩阵的右边界 r,同时用 l 表示子矩阵的左边界。
  • lr 都是从 1 开始,r 逐渐向右扩展。
关键条件
cpp 复制代码
while (l <= r && prefix[j][r] - prefix[j][l-1] - prefix[i-1][r] + prefix[i-1][l-1] > k) l++;
  • 这一行的作用是通过滑动窗口的方式,找到满足条件的最小左边界 l
  • prefix[j][r] - prefix[j][l-1] - prefix[i-1][r] + prefix[i-1][l-1] 计算的是子矩阵 (i, l)(j, r) 的和。
  • 如果当前子矩阵的和大于 k,则需要缩小窗口,即将左边界 l 向右移动,直到子矩阵的和不超过 k
关键更新
cpp 复制代码
if (l <= r) ans += r - l + 1;
  • 这一行是关键所在。
  • 在前面的 while 循环中,已经通过调整左边界 l,使得子矩阵 (i, l)(j, r) 的和不超过 k
  • 如果 l <= r,说明当前窗口是有效的,即存在满足条件的子矩阵。
  • r - l + 1 表示在当前的上下边界 (i, j) 和右边界 r 的情况下,所有可能的左边界 l 的数量。
举例说明

假设当前上下边界为 (i, j),右边界为 r,左边界 l 从 1 开始:

  • 如果子矩阵 (i, 1)(j, r) 的和不超过 k,那么子矩阵 (i, 2)(j, r)(i, 3)(j, r) 等等也一定满足条件。
  • 因此,所有满足条件的子矩阵数量是从 lr 的所有可能的左边界数量,即 r - l + 1

总结

if (l <= r) ans += r - l + 1; 这一行的作用是:

  • 在当前上下边界 (i, j) 和右边界 r 的情况下,统计所有满足条件的子矩阵数量。
  • 这些子矩阵的左边界从 lr,数量为 r - l + 1
相关推荐
ylfhpy32 分钟前
Java面试黄金宝典33
java·开发语言·数据结构·面试·职场和发展·排序算法
好好学习^按时吃饭4 小时前
蓝桥杯2024年第十五届省赛真题-R 格式
算法·蓝桥杯
wen__xvn4 小时前
每日一题洛谷P8664 [蓝桥杯 2018 省 A] 付账问题c++
c++·职场和发展·蓝桥杯
测试界茜茜4 小时前
接口测试和功能测试的区别
自动化测试·软件测试·功能测试·程序人生·职场和发展
ChoSeitaku5 小时前
NO.64十六届蓝桥杯备战|基础算法-简单贪心|货仓选址|最大子段和|纪念品分组|排座椅|矩阵消除(C++)
算法·矩阵·蓝桥杯
pipip.6 小时前
搜索二维矩阵
数据结构·算法·矩阵
序属秋秋秋7 小时前
算法基础_基础算法【位运算 + 离散化 + 区间合并】
c语言·c++·学习·算法·蓝桥杯
呵呵哒( ̄▽ ̄)"7 小时前
线性代数:分块矩阵,秩,齐次线性,非齐次线性的解相关经典例题
线性代数·机器学习·矩阵
梭七y7 小时前
【力扣hot100题】(048)二叉树的最近公共祖先
算法·leetcode·职场和发展
wgc2k8 小时前
吴恩达深度学习复盘(6)神经网络的矢量化原理
python·深度学习·矩阵