算法笔记(六):差分法
(6)差分法
目录
一、差分
1、介绍
2、定义
3、差分与前缀和
二、一维差分
1、定义
2、作用
3、方法
接下来是实战演练!!!
三、二维差分
1、定义
2、作用
3、方法
接下来是实战演练!!!
结论
写在最后!!!
一、差分
1、介绍
一般地,差分主要用于让一个序列某一特定范围内的所有值都加上或减去一个常数。
所以差分往往应用于线性的场合,即一维数组的环境,但是除此之外,差分还可以应用于二维数组,但是相比较一维数组,应用的较少。
2、定义
差分可以简单的看成序列中每个元素与其前一个元素的差。
3、差分与前缀和
const int N = 100010;
int n; //n数组长度
//定义两个一维整形数组 a为原数组,b为差分数组
int a[N],b[N]; //根据定义可知
b[i] = a[i] - a[i-1];
//稍微具体
b[1] = a[1];
b[2] = a[2] - a[1];
b[3] = a[3] - a[2];
...
b[i] = a[i] - a[i-1];//转化一下,求数组b的前缀和,根据上面公式可得b[1]+b[2]+b[3]+...+b[i]
= a[1]+(a[2]-a[1])+(a[3]-a[2])+...+(a[i]-a[i-1])
= a[i]//由此可知,原序列为差分序列的前缀和序列
a[i] = b[1]+b[2]+b[3]+...+b[i];
一般地,我们认为原序列就是差分序列的前缀和,所以把差分看做前缀和的逆运算
二、一维差分
1、定义
一维差分是指给定一个长度为n的序列a,要求支持操作pro(l,r,c)表示对a[l]~a[r]区间上的每一个值都加上或减去常数c,并求修改后的序列a。
2、作用
让一个序列中某个区间内的所有值均加上或减去一个常数。
可以将对a数组任意区间的同一操作优化到O(1)。
//区间[l,r]中的所有值都加上常数c
b[l] += c;
b[r+1] -= c;//上边语句实现原理 b相当于a的辅助数组
//把a序列分为[1,l-1],[l,r],[r+1,n]三部分,由差分定义和与前缀和关系可得
a[l-1] = b[1]+b[2]+...+b[l-1]; //b[1]~b[l-1]中所有值都未改变,a[l-1]也不变
a[l] = b[1]+b[2]+...+b[l-1]+b[l]; //b[1] += c,所以a[l] += c
a[l+1] = b[1]+b[2]+...+b[l-1]+b[l]+b[l+1]; //b[1] += c,所以a[l+1] += c
... //一直到
a[r] = b[1]+b[2]+...b[l]+...+b[r]; //b[1] += c,所以a[l+1] += c
a[r+1] = b[1]+b[2]+...b[l]+...+b[r]+b[r+1]; //b[l] += c,b[r+1] -= c;所以a[r+1]不变//所以由此可知上面的两个语句(b[l] += c;b[r+1] -= c)可以实现a数组在区间[l,r]内的所有值都加上了常数c
3、方法
对a数组区间[l,r]同时加上c的操作可转化为:
void insert(int l, int r, int c)
{b[l] += c;b[r+1] -= c;
}
while(m--)
{int l,r,c;scanf("%d%d%d",&l,&r,&c);insert(l,r,c);
}
对b数组求前缀和即可得到原数组a:
for(int i = 1; i <= n; i++)
{b[i] += b[i-1];printf("%d ",b[i]);
}
接下来是实战演练!!!
题目:
代码:
#include <iostream>
using namespace std;const int N = 100010;
int n,m;
int a[N],b[N];void insert(int l, int r, int c)
{b[l] += c;b[r+1] -= c;
}int main()
{scanf("%d%d",&n,&m);for(int i = 1; i <= n; i++){scanf("%d",&a[i]);}//插入for(int i = 1; i <= n; i ++){insert(i,i,a[i]);}while(m--){int l,r,c;scanf("%d%d%d",&l,&r,&c);insert(l,r,c);}for(int i = 1; i <= n; i++){b[i] += b[i-1];printf("%d ",b[i]);}return 0;
}
结果:
三、二维差分
1、定义
二维差分是指对于一个n*m的矩阵a,要求支持操作pro(x1,y1,x2,y2,a),表示对于以(x1,y1)为左上角,(x2,y2)为右下角的矩形区域,每个元素都加上常数a。求修改后的矩阵a。
2、作用
与一维差分一样二维差分可以把对矩阵的同一操作优化到O(1)。
图解:
3、方法
紫色矩形区域同时加上一个常数,由图可以得到插入函数:
void insert(int x1,int y1,int x2,int y2,int c)
{b[x1][y1] += c;b[x2+1][y1] -= c;b[x1][y2+1] -= c;b[x2+1][y2+1] += c;
}
初始化可以视为在(i,j)和(i,j)的小矩形内插入a[i][j];
for(int i = 1; i <= n; i++)
{for(int j = 1; j <= m; j++){insert(i,j,i,j,a[i][j]);}
}
对二维差分数组求二维前缀和可以得到原数组:
for(int i = 1; i <= n; i++)
{for(int j = 1; j <= m; j++){b[i][j] += b[i-1][j] + b[i][j-1] - b[i-1][j-1];printf("%d ",b[i][j]);}puts("");
}
接下来是实战演练!!!
题目:
代码:
#include <iostream>
using namespace std;const int N = 1010;
int n,m,q;
int a[N][N],b[N][N];void insert(int x1,int y1,int x2,int y2,int c)
{b[x1][y1] += c;b[x2+1][y1] -= c;b[x1][y2+1] -= c;b[x2+1][y2+1] += c;
}int main()
{scanf("%d%d%d",&n,&m,&q);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++){insert(i,j,i,j,a[i][j]);}}while(q--){int x1,y1,x2,y2,c;cin >> x1 >> y1 >> x2 >> y2 >> c;insert(x1,y1,x2,y2,c);}for(int i = 1; i <= n; i++){for(int j = 1; j <= m; j++){b[i][j] += b[i-1][j] + b[i][j-1] - b[i-1][j-1];}}for(int i = 1; i <= n; i++){for(int j = 1; j <= m; j++){printf("%d ",b[i][j]);}puts("");} return 0;
}
结果:
结论
树状数组插入和查询都可以优化到O(logn)。差分和前缀和适合用在查询或修改次数十分巨大的时候,当修改和查询在同一复杂度时适合用树状数组。
写在最后!!!
这是做的acwing创始人闫神讲的学习视频笔记,但是作为算法小白,知识还很不牢固。如果有错误请欢迎指正~~,感谢!!!
算法笔记(六):差分法相关推荐
- 算法笔记(六)多尺度特征融合之FPN/PANet
前言 最近论文快deadline了,一直没空更新-今天复习一下多尺度特征融合的常用操作. 1. FPN 特征金字塔 论文:feature pyramid networks for object det ...
- 数据结构与算法笔记(十六)—— 二叉搜索树
一.二叉搜索树定义 二叉搜索树(Binary Search Tree),又名二叉排序树(Binary Sort Tree). 二叉搜索树是具有有以下性质的二叉树: 若左子树不为空,则左子树上所有节点的 ...
- 算法笔记CodeUp第一至第六章刷题记录
文章目录 <算法笔记>2.2小节--C/C++快速入门->顺序结构 1.例题1-1-1 按要求输出信息(1) 2.例题1-1-2 按要求输出信息(2) 3.例题1-2-1 求两个整数 ...
- 《算法笔记》中文版 - 包括数组,链表,树,图,递归,DP,有序表等相关数据结构与算法的讲解及代码实现...
来源:专知本文为资源,建议阅读5分钟本文为你分享<算法笔记>中文版. https://github.com/Dairongpeng/algorithm-note 目录概览 第一节 复杂度. ...
- 吴恩达《机器学习》学习笔记六——过拟合与正则化
吴恩达<机器学习>学习笔记六--过拟合与正则化 一. 过拟合问题 1.线性回归过拟合问题 2.逻辑回归过拟合问题 3.过拟合的解决 二. 正则化后的代价函数 1.正则化思想 2.实际使用的 ...
- opencv 手选roi区域_【opencv学习笔记六】图像的ROI区域选择与复制
图像的数据量还是比较大的,对整张图片进行处理会影响我们的处理效率,因此常常只对图像中我们需要的部分进行处理,也就是感兴趣区域ROI.今天我们来看一下如何设置图像的感兴趣区域ROI.以及对ROI区域图像 ...
- 《算法笔记》学习 入门篇
目录 <算法笔记>学习 3.1 简单模拟 例1:[PAT B1001]害死人不偿命的(3n+1)猜想 例2:[PAT B1032]挖掘机技术哪家强 3.2 查找元素 例:[codeup 1 ...
- 算法笔记知识点整理大全
每次刷题都觉得自己吃了知识点不全,基础不牢固的亏,刷题的时候目标也不明确,于是看完了算法笔记并把知识点归纳了一下,当然直接看书会更加详细,这个归纳只是学习时加深印象以及方便自己之后回顾而已:之后刷题大 ...
- 《算法笔记》(胡凡)day1-C语言与C++入门
<算法笔记>(胡凡)day1-C语言和C 引言 C/C++快速入门 一.简介 二.数据类型的取值范围 1.整型 2.浮点型 二.常用的match函数 三.数组 1.memset-对数组中每 ...
- 金蝉素数c语言,算法笔记_204:第四届蓝桥杯软件类决赛真题(Java语言C组)
前言:以下代码仅供参考,若有错误欢迎指正哦~ 1好好学习 汤姆跟爷爷来中国旅游.一天,他帮助中国的小朋友贴标语.他负责贴的标语是分别写在四块红纸上的四个大字:"好.好.学.习".但 ...
最新文章
- 【Python】 linecache模块读取文件
- 我的世界java版怎么装在u盘_我的世界选择器参数怎么使用?
- [Java]Thinking in Java 练习2.12
- 事件(二):事件处理程序
- 更新无限无线连接更新服务器,02-H3C WBC560多业务无线控制器软件升级操作指导...
- php分流短信服务商,使用第三方短信服务商云片发送短信(php样例)
- 我参与的一个项目的继续总结:牢骚篇
- Spring帖子汇总
- java jui 正则表达式_正则表达式-Gorilla City-51CTO博客
- 陆振波的svm的matlab代码的解释,陆振波SVM的MATLAB代码解释
- stm8s103k3 周期 捕获_基于stm8s103k3单片机串口UART的正确使用分享
- Windows下使用c++编译hiredis.lib,Win32_Interop.lib
- 全球首个中文PaaS支撑平台----天翎myApps快速开发平台
- FLASH闪存编程原理与步骤
- 非形式逻辑(04)因果关系和推理
- python 邮件抄送是什么意思_python使用SMTP发邮件时使用Cc(抄送)和Bcc(密送)...
- ECMAScript和JavaScript的区别
- 职场人做会议记录的法宝——讯飞智能录音笔SR101
- YOLO V1 论文精讲
- GOM传奇引擎提示登陆器密码和网关密码不相同
热门文章
- android 虚拟技术打开,雷电安卓模拟器VT虚拟化打开方法教程
- 一般试卷的纸张大小是多少_试卷,考试试卷是多大的纸
- Kubernetes网络插件flannel和calico
- 2015年HEVC解码器组个人工作总结
- vue导出excel加一个进度条_vue项目中如何把数据导出成excel文件
- CCF之小明上学——2018.12 第一题 (java满分代码)
- 为什么MySQL InnoDB 存储引擎要用B+树做索引,而不用B树?
- ipad怎么和mac分屏_将Mac屏幕扩展到iPad有多好用?我甚至有了入手iPad Pro的冲动...
- vulnhub靶机-DC7-Writeup
- html中表格实现在页面居中显示,html中怎么把表格居中