【算法基础2】前缀和与差分

目录

  • 前缀和与差分
    • 1.综述
    • 2.前缀和
      • (1)一维前缀和
      • (2)二维前缀和(子矩阵的和)
    • 3.差分
      • (1)一维差分
      • (2)二维差分(差分矩阵)

前缀和与差分

1.综述

前缀和是某数列的前n项数的和,而差分则可以看做是前缀和的逆运算。前缀和与差分比起是一种算法,更像是一种解决问题的思路,通过构造一个特殊的数组,就可以让我们将某些复杂的问题简化。

2.前缀和

(1)一维前缀和

已知一个数列a[n],用S[n]来表示这个数列的前n项和数列。
S[i]=a[1]+a[2]+a[3]+…+a[i]
前缀和的用途:当我们要求数列a[n]的[l,r]区间内所有数的和,如果我们用一趟遍历的话,就需要O(n)的时间复杂度,而如果我们利用前缀和数组,就可以将其转化为S[r]-S[l-1],时间复杂度变成了O(1)。
S[r]=a[1]+a[2]+a[3]+…+a[l-1]+ a[l]+…+a[r]
S[l-1]=a[1]+a[2]+a[3]+…+a[l-1]
前缀和数组的预处理时间复杂度仍为O(n)。
这称为一维前缀和。

#include <bits/stdc++.h>using namespace std;const int N=1e6+10;int n,m;
int a[N],s[N];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++) s[i]=s[i-1]+a[i];//前缀和的初始化while(m--){int l,r;scanf("%d%d",&l,&r);int res=s[r]-s[l-1];//区间和的计算printf("%d\n",res);    }return 0;
}

(2)二维前缀和(子矩阵的和)

我们将前缀和扩展到二维矩阵中,将前n项的和转化为(x1,y1)坐标与(1,1)组成的矩阵中的所有数的和。而如果我们要求(x1,y1)(x2,y2)之间所有数的和,我们就可以利用前缀和的思路。
请添加图片描述
如图,将和分为三部分,可得子矩阵的和为
S[x2,y2]-S[x1-1,y2]-S[x2,y1-1]+S[x1-1,y1-1]。

#include <bits/stdc++.h>using namespace std;const int N=1010;int n,m,q;
int a[N][N],s[N][N];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++)s[i][j]=s[i-1][j]+s[i][j-1]-s[i-1][j-1]+a[i][j];while(q--){int  x1,y1,x2,y2;scanf("%d%d%d%d",&x1,&y1,&x2,&y2);printf("%d\n",s[x2][y2]-s[x1-1][y2]-s[x2][y1-1]+s[x1-1][y1-1]);}return 0;
}

3.差分

(1)一维差分

差分与前缀和可以看成是一对逆运算。我们通过一个原数组构造出其前缀和数组,对于差分来说,也可以构造出差分数组,而差分数组正好是前缀和数组逆过来的结果:
给定一个数组a[n],我们要构造一个新数组b[n],使得a[i]=b[1]+b[2]+…+b[i],可以看出a[n]成为了b[n]的前缀和数组,则我们称b[n]为a[n]的差分数组
而构造差分数组则比较简单,用数组项的差即可。
b[0]=a[0]
b[1]=a[1]-a[0]
b[2]=a[2]-a[1]

b[n]=a[n]-a[n-1]
通过O(n)的时间复杂度,我们就又能从b[n]得到a[n]。
差分的用途:给定一个数组a[n],我们现在要给数组的区间[l,r]中每一个数都加上c。如果要使用暴力循环加的话,时间复杂度就是O(n),现在我们利用差分数组,因为a[n]是b[n]的前缀和数组,所以当b[i]改变时,也会改变a[i]以及a[i]之后的每一个数,若b[i]+c,则a[i],a[i+1],…,a[n]都会+c,所以我们可以利用这个性质,让a[l]+c,然后再让a[r]-c,这样就能达成我们的目的了。
请添加图片描述
题目练习: AcWing 797. 差分

输入一个长度为n的整数序列。
接下来输入m个操作,每个操作包含三个整数l, r, c,表示将序列中[l, r]之间的每个数加上c。
请你输出进行完所有操作后的序列。

输入格式
第一行包含两个整数n和m。
第二行包含n个整数,表示整数序列。
接下来m行,每行包含三个整数l,r,c,表示一个操作。
输出格式
共一行,包含n个整数,表示最终序列。
代码

#include <bits/stdc++.h>using namespace std;const int N=1e6+10;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];for(int i=1;i<=n;i++) printf("%d",b[i]);return 0;
}

(2)二维差分(差分矩阵)

如果扩展到二维,我们需要让二维数组被选中的子矩阵中的每个元素的值加上c,是否也可以达到O(1)的时间复杂度。答案是肯定的,这就是二维差分。
a[][]数组是b[][]数组的前缀和数组,那么b[][]是a[][]的差分数组
原数组: a[i][j]
我们来构造差分数组: b[i][j]
使得a数组中a[i][j]是b数组左上角(1,1)到右下角(i,j)所包围矩形元素的和。
已知原数组a中被选中的子矩阵为以(x1,y1)为左上角,以(x2,y2)为右下角所围成的矩形区域
始终要记得,a数组是b数组的前缀和数组,比如对b数组的b[i][j]的修改,会影响到a数组中从a[i][j]及往后的每一个数。
假定我们已经构造好了b数组,类比一维差分,我们执行以下操作
来使被选中的子矩阵中的每个元素的值加上c
b[x1][y1]+=c;
b[x1,][y2+1]-=c;
b[x2+1][y1]-=c;
b[x2+1][y2+1]+=c;

#include <bits/stdc++.h>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,x2,y1,y2,c;scanf("%d%d%d%d%d",&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;
}

总之,前缀和与差分说是一种算法,不如说是一种思维方式,利用运算和构造数据结构的特点,我们就能将很多问题简单化。

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

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

相关文章

简介:基于Web的产品3D

基于 Web 的产品 3D 通过可视化界面获得各种选项来个性化他们的产品&#xff0c;例如颜色、材料、尺寸、文字、徽标、零件等。 在过去几年中&#xff0c;随着 3D 建模和渲染软件的出现&#xff0c;3D 渲染现在更常用于营销和促销目的。设计师、制造商和营销人员使用 3D 产品渲…

64B/66B编码

一、前言 8B/10B编码主要作用的优化直流平衡&#xff0c;从8bit中插2个bit进去&#xff0c;这样的话最终效果能够使长0或者长1的位数不超过5位&#xff0c;达到很好的效果。但是由于8B/10B编码的带宽利用率非常低&#xff0c;10G的带宽只有8G在传输有效数据&#xff0c;2G的带…

Java | Leetcode Java题解之第27题移除元素

题目&#xff1a; 题解&#xff1a; class Solution {public int removeElement(int[] nums, int val) {int left 0;int right nums.length;while (left < right) {if (nums[left] val) {nums[left] nums[right - 1];right--;} else {left;}}return left;} }

GAN:对抗生成网络【通俗易懂】

一、概述 对抗生成网络&#xff08;GAN&#xff09;是一种深度学习模型&#xff0c;由两个神经网络组成&#xff1a;生成器G和判别器D。这两个网络被训练来协同工作&#xff0c;以生成接近真实数据的新样本。 生成器的任务是接收一个随机噪声向量&#xff0c;并将其转换为与真…

【Linux】基础IO----理解缓冲区

> 作者&#xff1a;დ旧言~ > 座右铭&#xff1a;松树千年终是朽&#xff0c;槿花一日自为荣。 > 目标&#xff1a;理解缓冲区 > 毒鸡汤&#xff1a;有些事情&#xff0c;总是不明白&#xff0c;所以我不会坚持。早安! > 专栏选自&#xff1a;Linux初阶 > 望…

C++11---多线程

看前须知&#xff1a;如果对线程不了解的&#xff0c;可以先去看Linux---多线程(上)&#xff0c;(下)这两篇文章 那里主要讲了线程的一些基础概念和底层相关理解&#xff0c;对我们阅读这篇文章会有所帮助 一、thread --- 线程 1、thread相关接口介绍 在C11之前&#xff0c;涉…

第7期 部署两地三中心解决方案SDRS+CBR

第7期 部署两地三中心解决方案SDRSCBR 1.实施步骤&#xff08;部署跨可用区容灾&#xff09;配置跨可用区容灾操作场景约束与限制创建保护组 什么是SDRS什么是CBR什么是两地三中心容灾方案&#xff08;SDRSCBR&#xff09;应用场景方案优势三种容灾方案对比 2.两地三中心方案原…

边缘计算【智能+安全检测】系列教程--使用OpenCV+GStreamer实现真正的硬解码,完全消除马赛克

通过现有博客的GST_URL = "rtspsrc location=rtsp://admin:abcd1234@192.168.1.64:554/h264/ch01/main/av_stream latency=150 ! rtph264depay ! avdec_h264 ! videorate ! videoconvert ! appsink sync=false" GStreamer的解码方式解码,大多情况应该存在上图马赛克…

C/C++ BM25二叉树的后序遍历

文章目录 前言题目解决方案一1.1 思路阐述1.2 源码 解决方案二总结 前言 和前序遍历中序遍历一致&#xff0c;换个顺序就行。 详情参考C/C BM23 二叉树的前序遍历 详情参考C/C BM24 二叉树的中序遍历 题目 给定一个二叉树&#xff0c;返回他的后序遍历的序列。 后序遍历是值…

etcd相关知识整理归纳 —— 筑梦之路

什么是etcd? Etcd 是 CoreOS 团队于2013年6月发起的开源项目&#xff0c;它的目标是构建一个高可用的分布式键值(key-value)数据库。etcd内部采用raft协议作为一致性算法&#xff0c;Etcd基于 Go 语言实现。 名字由来&#xff0c;它源于两个方面&#xff0c;unix的“/etc”文件…

Mathorcup 甲骨文识别

本资源主要包含第2-4问&#xff0c;第一问直接使用传统图像处理即可&#xff0c;需要有很多步骤&#xff0c;这一步大家自己写就行。 2 第2问&#xff0c;甲骨文识别 2.1 先处理源文件 原文件有jpg和json文件&#xff0c;都在一个文件夹下&#xff0c;需要对json文件进行处理…

Windows环境下删除MySQL

文章目录 一、关闭MySQL服务1、winR打开运行&#xff0c;输入services.msc回车2、服务里找到MySQL并停止 二、卸载MySQL软件1、打开控制模板--卸载程序--卸载MySQL相关的所有组件 三、删除MySQL在物理硬盘上的所有文件1、删除MySQL的安装目录&#xff08;默认在C盘下的Program …