统计子矩阵

一、题目描述

P8783 [蓝桥杯 2022 省 B] 统计子矩阵

二、算法简析

2.1 二维前缀和

我们知道,只要确定了矩阵的左上顶点和右下顶点,一个矩阵就被固定了。因此,我们可以遍历这两个顶点,达到遍历所有子矩阵的目的,复杂度会达到 O ( N 2 ∗ M 2 ) O(N^2*M^2) O(N2M2)。确定了子矩阵,就要判断子矩阵的值是否不大于 K K K。 如何能高效地得到子矩阵的值呢?答案是二维前缀和
与普通的前缀和不同,二维前缀和 psum[i][j] = \text{psum[i][j]}= psum[i][j]= 左上顶点 ( 1 , 1 ) (1, 1) (1,1)、右下顶点 ( i , j ) (i, j) (i,j) 确定的子矩阵的值。通过以下表达式,可以得到二维前缀和:

psum[i][j] = psum[i][j - 1] + psum[i - 1][j] - psum[i - 1][j - 1] + A[i][j] \text{psum[i][j] = psum[i][j - 1] + psum[i - 1][j] - psum[i - 1][j - 1] + A[i][j]} psum[i][j] = psum[i][j - 1] + psum[i - 1][j] - psum[i - 1][j - 1] + A[i][j]

有了二维前缀和,就可以以 O ( 1 ) O(1) O(1) 确定左上角 ( x 1 , y 1 ) (x1, y1) (x1,y1)、右下角 ( x 2 , y 2 ) (x2, y2) (x2,y2) 的子矩阵的值:

matrix_val = psum[x2][y2] - psum[x1 - 1][y2] - psum[x2][y1 - 1] + psum[x1 - 1][y1 - 1] \text{matrix\_val = psum[x2][y2] - psum[x1 - 1][y2] - psum[x2][y1 - 1] + psum[x1 - 1][y1 - 1]} matrix_val = psum[x2][y2] - psum[x1 - 1][y2] - psum[x2][y1 - 1] + psum[x1 - 1][y1 - 1]

但是,该算法的复杂度仍然有 O ( N 2 ∗ M 2 ) O(N^2*M^2) O(N2M2),会 LTE


2.2 压缩维度 + 双指针

压缩维度:我们可以把二维矩阵压缩至一维:画两条线,high 表示矩阵上界(左上点只能在该行)、low表示矩阵下界(右下点只能在该行)。因此,由 highlow 确定的子矩阵只能由列矩阵组合而成,所以按列压缩,即按列求和。
图1
通过遍历 highlow,我们可以得到所有组成子矩阵的列矩阵。

双指针:通过上文的压缩,我们得到了“子矩阵的零件”。为了得到该情况下的所有子矩阵,肯定要用双指针遍历压缩数组,得到所有组合方式。

int B[4];   // 压缩后的结果for (int i = 0; i < 4; i++)for (int j = i; j < 4; j++)\\ ...

显然,指针 j 发生了回溯,导致复杂度达到了 O ( n 2 ) O(n^2) O(n2)。如何避免发生回溯呢?利用单调性,我们可以把复杂度降为 O ( n ) O(n) O(n)
我们规定 area(left, right) = B[left] + B[left + 1] + ... + B[right] \text{area(left, right) = B[left] + B[left + 1] + ... + B[right]} area(left, right) = B[left] + B[left + 1] + ... + B[right]
area(left, right) <= K \text{area(left, right) <= K} area(left, right) <= K left + 1 <= right \text{left + 1 <= right} left + 1 <= right,则 area(left + 1, right) <= K \text{area(left + 1, right) <= K} area(left + 1, right) <= K
area(left, right) > K \text{area(left, right) > K} area(left, right) > K right + 1 <= M \text{right + 1 <= M} right + 1 <= M,则 area(left, right + 1) > K \text{area(left, right + 1) > K} area(left, right + 1) > K
显然, area(left, right) \text{area(left, right)} area(left, right) left \text{left} left 单调递减,随 right \text{right} right 单调递增

利用单调性,我们可以得到以下结果:

  • 1、随 left \text{left} left 单调递减,若 area(left, right) <= K \text{area(left, right) <= K} area(left, right) <= K,则一共有 right - left + 1 \text{right - left + 1} right - left + 1 种组合方式。
  • 2、我们只需要遍历 right 就能得到所有子矩阵。因为单调性,若 area(left, right) > K \text{area(left, right) > K} area(left, right) > K,只需要 left++ \text{left++} left++,直到 area(left, right) <= K \text{area(left, right) <= K} area(left, right) <= K
int B[4];   // 压缩后的结果int left = 1, right = 1;
ll tmp = 0;
for (; right <= 4; right++)
{tmp += B[right];if (tmp <= K)ans += right - left + 1;else{while (tmp > K){tmp -= B[left];left++;	}ans += right - left + 1;}	
} 

三、AC代码

#include <bits/stdc++.h>using namespace std;const int MAX = 505;
typedef long long ll;int A[MAX][MAX], N, M, K;
ll ans, psum[MAX][MAX], B[MAX];int quickin(void)
{int ret = 0;char ch = getchar();while (ch < '0' || ch > '9')ch = getchar();while (ch >= '0' && ch <= '9' && ch != EOF){ret = ret * 10 + ch - '0';ch = getchar();}return ret;
}void init(void)
{for (int i = 1; i <= N; i++)for (int j = 1; j <= M; j++)psum[i][j] = psum[i - 1][j] + A[i][j];
}void solve(void)
{for (int high = 1; high <= N; high++){for (int low = high; low <= N; low++){for (int i = 1; i <= M; i++)B[i] = psum[low][i] - psum[high - 1][i];int left = 1, right = 1;ll tmp = 0;for (; right <= M; right++){tmp += B[right];if (tmp <= K)ans += right - left + 1;else{while (tmp > K){tmp -= B[left];left++;	}ans += right - left + 1;}	} }}cout << ans << endl;
}int main()
{#ifdef LOCALfreopen("test.in", "r", stdin);#endifN = quickin(), M = quickin(), K = quickin();for (int i = 1; i <= N; i++)for (int j = 1; j <= M; j++)A[i][j] = quickin();init();solve();return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/710606.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

AutoSAR(基础入门篇)12.5-Dem

目录 一、Dem简介 二、Dem消抖 1、计数模式 1. 普通增减计数 2. 反向归零增减模式

在微服务整合dubbo,以为微服务版的若依为例

在微服务整合dubbo&#xff0c;以为微服务版的若依为例 一、环境二、整合过程1、父模块依赖2、生产者3、消费者 三、修改若依的服务调用方式为dubbo1、改造系统模块2、改造认证授权中心 四、整合过程遇到的问题1、出现循环引用2、出现依赖冲突3、启动出现端口号被占用4、出现某…

UVa11726 Crime Scene

题目链接 UVa11726 - Crime Scene 题意 给定n&#xff08;n≤100&#xff09;个物体&#xff0c;每个物体都是一个圆或者k&#xff08;k≤10&#xff09;边形&#xff0c;用长度尽量小的绳子把它们包围起来。 分析 孟加拉国Manzurur Rahman Khan (Sidky)大神出的难题&#xff…

MySQL 核心模块揭秘 | 07 期 | 二阶段提交 (1) prepare 阶段

二阶段提交的 prepare 阶段&#xff0c;binlog 和 InnoDB 各自会有哪些动作&#xff1f; 本文基于 MySQL 8.0.32 源码&#xff0c;存储引擎为 InnoDB。 1. 二阶段提交 二阶段提交&#xff0c;顾名思义&#xff0c;包含两个阶段&#xff0c;它们是&#xff1a; prepare 阶段。…

springboot-基础-eclipse配置+helloword示例

备份笔记。所有代码都是2019年测试通过的&#xff0c;如有问题请自行搜索解决&#xff01; 下一篇&#xff1a;springboot-基础-添加model和controller的简单例子常用注解含义 目录 配置helloword示例新建项目创建文件 配置 spring boot官方有定制版eclipse&#xff0c;也就是…

BUUCTF AWD-Test1

打开靶场是这个有些简陋的界面。 随便点点&#xff0c;找到这个东西。 看到ThinkPHP&#xff0c;思路瞬间清晰&#xff0c;老熟人了。这个就是ThinkPHP漏洞。根据版本我们去找一下poc。 /index.php/?sIndex/\think\View/display&content%22%3C?%3E%3C?php%20phpinfo();…

SHELL 脚本: 导出NEO4j DUMP并上传SFTP

前提 开通sftp账号 安装expect 示例 NEO4J_HOME/path/to/neo4j # neo4j 安装目录 DUMP_PATH/data/dump # DUMP本地保存目录 DUMP_FILEneo4j_$(date %F).dump #导出文件名称 UPLOAD_DIR/path/to/stfp/dump/ #上传目录 $NEO4J_HOME/bin/neo4j-admin dump --databaseneo4j --t…

Vue-5

Vue 3 的优势 更容易维护&#xff08;组合式API&#xff09;更快的速度更小的体积更优的数据响应 创建 Vue 3 项目 前提环境条件&#xff1a;已安装 16.0 或更高版本的 Node.js node -v创建一个 Vue 应用&#xff08;下面的指令将会安装并执行 create-vue &#xff09; np…

服务端向客户端推送数据的实现方案

在日常的开发中&#xff0c;我们经常能碰见服务端需要主动推送给客户端数据的业务场景&#xff0c;比如数据大屏的实时数据&#xff0c;比如消息中心的未读消息&#xff0c;比如聊天功能等等。 本文主要介绍SSE的使用场景和如何使用SSE。 服务端向客户端推送数据的实现方案有哪…

MySQL 自增列解析(Auto_increment)

MySQL数据库为列提供了一种自增属性&#xff0c;当列被定义为自增时。Insert语句对该列即使不提供值&#xff0c;MySQL也会自动为该列生成递增的唯一标识&#xff0c;因此这个特性广泛用于主键的自动生成。 一、自增列的用法 自增列具有自动生成序列值&#xff0c;整型&#…

职责链模式(Chain of Responsibility Pattern)

定义 职责链模式&#xff08;Chain of Responsibility Pattern&#xff09;是一种行为设计模式&#xff0c;它允许对象接收请求并将其沿着处理者链传递&#xff0c;直到有一个处理者处理它为止。职责链模式通过将请求的处理逻辑分布 在职责链模式中&#xff0c;通常包含以下几…

MYSQL04高级_逻辑架构剖析、查询缓存、解析器、优化器、执行器、存储引擎

文章目录 ①. 逻辑架构剖析②. 服务层 - 查询缓存③. 服务层 - 解析器④. 服务层 - 优化器⑤. 服务层 - 执行器⑥. MySQL8执行原理 ①. 逻辑架构剖析 ①. 服务器处理客户端请求 ②. 连接层 系统(客户端)访问MySQL服务器前,做的第一件事就是建立TCP连接经过三次握手建立连接成…

Linux使用C语言实现通过互斥锁限制对共享资源的访问

互斥锁限制共享资源的访问 主线程中有两个线程&#xff0c;分别输出信息。 #include <stdio.h> #include <pthread.h> #include <unistd.h>int g_data0;void* fun1(void *arg) {printf("t1&#xff1a;%ld thread is create\n", (unsigned long)…

大宋咨询数据研究在汽车新品上市中的核心作用

随着汽车行业的快速变革&#xff0c;数据研究已经成为新品上市流程中的不可或缺的一环。从市场定位、产品规划到营销策略&#xff0c;数据研究不仅为汽车企业提供了独特的洞察&#xff0c;还为其提供了决策依据&#xff0c;确保新品在竞争激烈的市场中取得优势。在这一领域&…

Kubernetes IoTDB系列 | IoTDB搭建 | v1.3.0

目录 一、IoTDB 介绍二、k8s 部署 IoTDB一、IoTDB 介绍 IoTDB 是一种面向物联网(IoT)场景的开源时序数据库。它专门设计用于高效地存储和查询大规模物联网设备产生的时序数据。IoTDB 提供了高吞吐量、低延迟、灵活的数据模型以及多种数据查询和存储引擎等特性,使其成为处理…

稀疏图带负边的全源最短路Johnson算法

BellmanFord算法 Johnson算法解决的问题 带负权的稀疏图的全源最短路 算法流程 重新设置的每条边的权重都大于或等于0&#xff0c;跑完Djikstra后得到的全源最短路&#xff0c;记得要还原&#xff0c;即&#xff1a;f(u,v) d(u,v) - h[u] h[v] 例题

45、WEB攻防——通用漏洞PHP反序列化POP链构造魔术方法原生类

文章目录 序列化&#xff1a;将java、php等代码中的对象转化为数组或字符串等格式。代表函数serialize()&#xff0c;将一个对象转换成一个字符&#xff1b;反序列化&#xff1a;将数组或字符串等格式还成对象。代表函数unserialize()&#xff0c;将字符串还原成一个对象。 P…

MWC 2024丨Smart Health搭载高通Aware平台—美格发布智能健康看护解决方案,开启健康管理新体验

2月29日&#xff0c;在MWC 2024世界移动通信大会上&#xff0c;全球领先的无线通信模组及解决方案提供商——美格智能正式发布了新一代Cat.1模组SLM336Q&#xff0c;是中低速物联网应用场景的高性价比之选。本次还发布了首款搭载高通Aware™平台的智能看护解决方案MC303&#x…

[万字长文] 从 Vue 3 的项目模板学习 tsconfig 配置

文章目录 一、tsconfig.json 的作用二、基本介绍三、Vue 3 的 tsconfig.json 的结构分析1. 总配置 tsconfig.json2. Web 侧 tsconfig.app.jsona. 继承基础配置b. 包含和排除的文件c. 编译器选项 3. 测试 tsconfig.vitest.jsona. 继承的基础配置b. 包含和排除的文件c. 编译器选项…

OD(13)之Mermaid饼图和象限图

OD(13)之Mermaid饼图和象限图使用详解 Author: Once Day Date: 2024年2月29日 漫漫长路才刚刚开始… 全系列文章可参考专栏: Mermaid使用指南_Once_day的博客-CSDN博客 参考文章: 关于 Mermaid | Mermaid 中文网 (nodejs.cn)Mermaid | Diagramming and charting tool‍‌⁡…