当前位置: 首页 > news >正文

二维差分算法详解

牛客测试链接

二维差分模板

问题描述

给定一个n行m列的矩阵,下标从1开始。接下来有q次操作,每次操作输入5个参数x1, y1, x2, y2, k,表示把以(x1, y1)为左上角,(x2,y2)为右下角的子矩阵的每个元素都加上k。请输出操作后的矩阵。

输入描述

第一行包含三个整数n,m,q。接下来n行,每行m个整数,代表矩阵的元素。接下来q行,每行5个整数x1, y1, x2, y2, k,分别代表这次操作的参数。

输出描述

输出n行,每行m个数,每个数用空格分开,表示这个矩阵。

算法思路

二维差分算法是一种用于解决矩阵区间更新问题的高效算法。它通过预处理和差分数组的方式,将区间更新的时间复杂度从O(nm)降低到O(1)。

具体步骤如下:

  1. 定义一个大小为(n+1)*(m+1)的差分数组diff,用于存储每个位置的差分值。
  2. 遍历矩阵的每个元素,将其加到差分数组对应位置上。
  3. 对差分数组进行预处理,计算每个位置的前缀和,即diff[i][j]表示原矩阵中(1,1)到(i,j)位置的元素和。
  4. 对每次操作,将对应区间的四个角的差分值进行更新,即diff[a][b] += k, diff[c+1][d+1] += k, diff[c+1][b] -= k, diff[a][d+1] -= k。
  5. 对差分数组进行再次预处理,计算每个位置的前缀和,即diff[i][j]表示操作后的矩阵中(1,1)到(i,j)位置的元素和。
  6. 输出操作后的矩阵。

代码实现

import java.util.Scanner;
import java.io.*;public class Main {static BufferedReader in = new BufferedReader(new InputStreamReader(System.in));static PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));static StreamTokenizer sr = new StreamTokenizer(in);static int MAXN = 1005;static int n, m, q;static long[][] diff = new long[MAXN][MAXN];static void build() {for (int i = 1; i <= n; i++) {for (int j = 1; j <= m; j++) {diff[i][j] += diff[i - 1][j] + diff[i][j - 1] - diff[i - 1][j - 1];}}}static void clear() {for (int i = 1; i <= n + 1; i++) {for (int j = 1; j <= m + 1; j++) {diff[i][j] = 0;}}}static void add(int a, int b, int c, int d, int k) {diff[a][b] += k;diff[c + 1][d + 1] += k;diff[c + 1][b] -= k;diff[a][d + 1] -= k;}static int nextInt() throws IOException {sr.nextToken();return (int)sr.nval;}public static void main(String[] args) throws IOException {n = nextInt();m = nextInt();q = nextInt();for (int i = 1; i <= n; i++) {for (int j = 1; j <= m; j++) {add(i, j, i, j, nextInt());}}while (q-- > 0) {int a = nextInt();int b = nextInt();int c = nextInt();int d = nextInt();int k = nextInt();add(a, b, c, d, k);}build();for (int i = 1; i <= n; i++) {for (int j = 1; j <= m; j++) {out.print(diff[i][j] + " ");}out.println();out.flush();}clear();}
}

总结

二维差分算法是一种高效解决矩阵区间更新问题的算法。通过预处理和差分数组的方式,可以将区间更新的时间复杂度从O(nm)降低到O(1)。在实际应用中,可以大大提高算法的效率。

相关文章:

  • Sentinel限流、熔断
  • Codeforces Round 768 (Div. 1) D. Flipping Range(思维题 等价类性质 dp)
  • javacv和opencv对图文视频编辑-常见错误汇总
  • C++学习笔记——SLT六大组件及头文件
  • Java项目:117SpringBoot动漫论坛网站
  • 前端随机验证码安全验证sdk
  • 【EMC专题】浪涌的成因与ICE 61000-4-5标准
  • 训练AI模型:寻找最优参数a和b
  • stm32学习笔记:USART串口通信
  • Day02
  • 远程登陆利器 ssh
  • C# 静态代码织入AOP组件之肉夹馍
  • 剑指offer面试题5 从尾到头打印链表
  • 第二百六十六回
  • Nano文本编辑器:轻松入门,简单实用(适用于Linux)
  • ----------
  • [LeetCode] Wiggle Sort
  • 【402天】跃迁之路——程序员高效学习方法论探索系列(实验阶段159-2018.03.14)...
  • 2017 年终总结 —— 在路上
  • CSS3 变换
  • Github访问慢解决办法
  • IP路由与转发
  • JavaScript设计模式与开发实践系列之策略模式
  • leetcode98. Validate Binary Search Tree
  • LeetCode刷题——29. Divide Two Integers(Part 1靠自己)
  • 基于遗传算法的优化问题求解
  • 漫谈开发设计中的一些“原则”及“设计哲学”
  • 前端工程化(Gulp、Webpack)-webpack
  • 说说动画卡顿的解决方案
  • 算法之不定期更新(一)(2018-04-12)
  • 提醒我喝水chrome插件开发指南
  • 延迟脚本的方式
  • 怎么将电脑中的声音录制成WAV格式
  • ​​​​​​​​​​​​​​Γ函数
  • ​二进制运算符:(与运算)、|(或运算)、~(取反运算)、^(异或运算)、位移运算符​
  • ​一些不规范的GTID使用场景
  • !!【OpenCV学习】计算两幅图像的重叠区域
  • # Swust 12th acm 邀请赛# [ K ] 三角形判定 [题解]
  • (06)金属布线——为半导体注入生命的连接
  • (android 地图实战开发)3 在地图上显示当前位置和自定义银行位置
  • (C#)if (this == null)?你在逗我,this 怎么可能为 null!用 IL 编译和反编译看穿一切
  • (cljs/run-at (JSVM. :browser) 搭建刚好可用的开发环境!)
  • (笔记)Kotlin——Android封装ViewBinding之二 优化
  • (第27天)Oracle 数据泵转换分区表
  • (附源码)springboot 个人网页的网站 毕业设计031623
  • (附源码)springboot 智能停车场系统 毕业设计065415
  • (终章)[图像识别]13.OpenCV案例 自定义训练集分类器物体检测
  • (转)C#调用WebService 基础
  • (转)负载均衡,回话保持,cookie
  • (转)拼包函数及网络封包的异常处理(含代码)
  • .NET 8 中引入新的 IHostedLifecycleService 接口 实现定时任务
  • .NET/C# 使用 SpanT 为字符串处理提升性能
  • /etc/sudoer文件配置简析
  • @PreAuthorize注解
  • @Query中countQuery的介绍