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

【算法笔记】前缀和与差分

第一课前缀和与差分

算法是解决问题的方法与步骤。

在看一个算法是否优秀时,我们一般都要考虑一个算法的时间复杂度空间复杂度

现在随着空间越来越大,时间复杂度成为了一个算法的重要指标,那么如何估计一个算法的时间复杂度呢?

常见的时间复杂度:O(1) O(logn) O(n) O(nlogn) O(n2) O(2n) O(n!)

1.时间复杂度

时间复杂度:分析算法的执行效率。

示例:

时间复杂度为O(1)

int fun(int n){int i=n;int j=3*n;return i+j;
}

时间复杂度为O(logn)

int fun(int n){int i=1;while(i<=n)i*=2;return i;
}

时间复杂度为O(n)

int fun(int n){int sum=0;for(int i=0;i<n;i++){sum+=i;}return sum;
}

时间复杂度为O(m+n)

int fun(int m,int n){int sum=0;for(int i=1;i<=m;i++)sum+=i;for(int i=1;i<=n;i++)sum+=i;return sum;
}

时间复杂度为O(mlogn)

int fun(int m,int n){int sum=0;for(int i=0;i<m;i++){for(int j=0;j<n;j++){sum+=i*j;j=j*2;}}return sum;
}

时间复杂度为O(n2)

int fun(int n){int sum=0;for(int i=0;i<n;i++){for(int j=0;j<n;j++){sum+=i*j;}}return sum;
}

时间复杂度为O(n!)

void fun(int k, int n) { //k==nif (k == 1) {return;}for (int i = n - k ; i < n; i++) {fun(k - 1, n);}
}

常见的时间复杂度:O(1)<O(logn)<O(n)<O(nlogn)<O(n2)<O(2n)<O(n!)

通常情况下,竞赛环境中要求运行时间为1秒。计算机1秒可以执行的次数为10亿次。10^9

在这里插入图片描述

2.空间复杂度

空间复杂度:算法所占内存空间。

空间复杂度为O(1)

int fun(int n){int sum=0;for(int i=0;i<n;i++)sum+=i;return sum;
}

空间复杂度为O(n)

int fun(int n)
{int arr[N];while(i<=N)i=i*2;return i;
}

空间复杂度为O(MN)

int fun(int m,int n)
{int arr[M][N];for(int i=1;i<=m;i++)for(int j=1;j<=n;j++)sum+=arr[i][j];return sum;
}

**常见的时间复杂度:O(1) < O(n) < O(n2) **

3.一维前缀和

前缀和可以用于快速计算一个序列的区间和,也有很多问题里不是直接用前缀和,但是借用了前缀和的思想。

3.1 概念

预处理出一个前缀和数组后,要求一段区间和可以使用O(1)的时间复杂度快速求出。

公式:

预处理:s[i]=a[i]+a[i-1]

求区间[l,r]:sum=s[r]-s[l-1]

'‘前缀和数组’‘和’‘原数组’'可以合二为一

3.2 例题

输入一个长度为 n 的整数序列。

接下来再输入 m 个询问,每个询问输入一对 l,r。

对于每个询问,输出原序列中从第 l 个数到第 r 个数的和。

输入格式

第一行包含两个整数 n 和 m。

第二行包含 n 个整数,表示整数数列。

接下来 m 行,每行包含两个整数 l 和 r,表示一个询问的区间范围。

输出格式

共 m 行,每行输出一个询问的结果。

数据范围

1≤l≤r≤n
1≤n,m≤100000
−1000≤数列中元素的值≤1000

输入样例:

5 3
2 1 3 6 4
1 2
1 3
2 4

输出样例:

3
6
10

AC代码:

#include <iostream>using namespace std;const int N=100010;int a[N];int main(){int n,m;scanf("%d",&n);for(int i=1;i<=n;i++)scanf("%d",&a[i]);for(int i=1;i<=n;i++)a[i]=a[i-1]+a[i];scanf("%d",&m);while(m--){int l,r;scanf("%d%d",&l,&r);printf("%d\n",a[r]-a[l-1]);}return 0;
}

4.二维前缀和

二维前缀和记录的是在一个二维矩阵中,从左上角开始到矩阵的某个点构成的子矩阵中所有元素的和。

4.1 概念

预处理出一个前缀和二维数组后,要求一段二维区间和可以使用O(1)的时间复杂度快速求出。

计算矩阵的前缀和:s[x][y] = s[x - 1][y] + s[x][y -1] - s[x -1][y-1] + a[x][y]

在这里插入图片描述

计算子矩阵的和:计算子矩阵的和:s = s[x2][y2] - s[x1 - 1][y2] - s[x2][y1 - 1] + s[x1 - 1][y1 -1]

在这里插入图片描述

4.2 例题

输入一个 n 行 m 列的整数矩阵,再输入 q 个询问,每个询问包含四个整数 x1,y1,x2,y2,表示一个子矩阵的左上角坐标和右下角坐标。

对于每个询问输出子矩阵中所有数的和。

输入格式

第一行包含三个整数 n,m,q。

接下来 n 行,每行包含 m 个整数,表示整数矩阵。

接下来 q 行,每行包含四个整数 x1,y1,x2,y2,表示一组询问。

输出格式

共 q 行,每行输出一个询问的结果。

数据范围

1≤n,m≤1000
1≤q≤200000
1≤x1≤x2≤n
1≤y1≤y2≤m
−1000≤矩阵内元素的值≤1000−1000≤矩阵内元素的值≤1000

输入样例:

3 4 3
1 7 2 4
3 6 2 8
2 1 2 3
1 1 2 2
2 1 3 4
1 3 3 4

输出样例:

17
27
21

AC代码:

#include <iostream>using namespace std;int s[1010][1010];int n,m,q;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",&s[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];while(q--){int x1,y1,x2,y2;scanf("%d%d%d%d",&x1,&y1,&x2,&y2);printf("%d\n",s[x2][y2]-s[x2][y1-1]-s[x1-1][y2]+s[x1-1][y1-1]);}return 0;
}

5.一维差分

5.1 差分数组的定义及用途

1.定义:对于已知有n个元素的离线数列a,我们可以建立记录它每项与前一项差值的差分数组b:显然,b[1]=a[1]-0=a[1];对于整数i∈[2,n],我们让b[i]=a[i]-a[i-1]。

2.简单性质:
(1)计算数列各项的值:观察a[2]=b[1]+b[2]=a[1]+a[2]-a[1]=a[2]可知,数列第i项的值是可以用差分数组的前i项的和计算的,即a[i]=b[i]的前缀和。

差分是前缀和的逆运算,对于一个数组a,其差分数组b的每一项都是a [ i ]和前一项a [ i − 1 ]的差。
b [ i ] = a [ i ] − a [ i − 1 ]
通过差分数组b,求b的前缀和,就可以求得原数组a的每项值。
和前缀和类似的,也是要留出索引是0的位置b [0]=0,方便计算。

注意:差分数组和原数组必须分开存放!!!!

5.2 例题

输入一个长度为 n 的整数序列。

接下来输入 m 个操作,每个操作包含三个整数 l,r,c表示将序列中 [l,r][,] 之间的每个数加上 c。

请你输出进行完所有操作后的序列。

输入格式

第一行包含两个整数 n 和 m。

第二行包含 n 个整数,表示整数序列。

接下来 m 行,每行包含三个整数 l,r,c表示一个操作。

输出格式

共一行,包含 n 个整数,表示最终序列。

数据范围

1≤n,m≤100000
1≤l≤r≤n
−1000≤c≤1000
−1000≤整数序列中元素的值≤1000

输入样例:

6 3
1 2 2 1 2 1
1 3 1
3 5 1
1 6 1

输出样例:

3 4 5 3 4 2

AC代码:

#include <iostream>using namespace std;
int a[100010],s[100010];int main(){int n,m;cin>>n>>m;for(int i=1;i<=n;i++)cin>>a[i];   for(int i=1;i<=n;i++)s[i]=a[i]-a[i-1];// 读入并计算差分数组while(m--){int l,r,c;cin>>l>>r>>c;s[l]+=c;s[r+1]-=c;// 在原数组中将区间[l, r]加上c}for(int i=1;i<=n;i++){s[i]+=s[i-1];cout<<s[i]<<' ';}// 给差分数组计算前缀和,就求出了原数组return 0;
}

6.二维差分(矩阵)

6.1 二维差分的定义

二维差分用于在一个矩阵里,快速里把矩阵的一个子矩阵加上一个固定的数。也是直接来修改差分矩阵。试想只要在差分矩阵的( x 1 , y 1 ) 位置加上c,那么以它为左上角,所有后面的元素就都加上了c。要让( x 2 , y 2 ) 的右边和下边的元素不受影响,由容斥原理可以知道,只要在( x 2 + 1 , y 1 ) 和( x 1 , y 2 + 1 ) 位置减去c,再从( x 2 + 1 , y 2 + 1 ) 位置加回c就可以了。

在这里插入图片描述

6.2 例题

输入一个 n 行 m 列的整数矩阵,再输入 q 个操作,每个操作包含五个整数 x1,y1,x2,y2,c,,其中 (x1,y1) 和 (x2,y2) 表示一个子矩阵的左上角坐标和右下角坐标。

每个操作都要将选中的子矩阵中的每个元素的值加上 c。

请你将进行完所有操作后的矩阵输出。

输入格式

第一行包含整数 n,m,q。

接下来 n 行,每行包含 m 个整数,表示整数矩阵。

接下来 q 行,每行包含 5 个整数 x1,y1,x2,y2,c表示一个操作。

输出格式

共 n 行,每行 m 个整数,表示所有操作进行完毕后的最终矩阵。

数据范围

1≤n,m≤1000
1≤q≤100000
1≤x1≤x2≤n
1≤y1≤y2≤m
−1000≤c≤1000
−1000≤矩阵内元素的值≤1000

输入样例:

3 4 3
1 2 2 1
3 2 2 1
1 1 1 1
1 1 2 2 1
1 3 2 3 2
3 1 3 4 1

输出样例:

2 3 4 1
4 3 4 1
2 2 2 2

AC代码:

#include<iostream>
#include<cstdio>
using namespace std;
const int N = 1e3 + 10;
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()
{int n, m, q;cin >> n >> m >> q;for (int i = 1; i <= n; i++)for (int j = 1; j <= m; j++)cin >> 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);//加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]);}printf("\n");}return 0;
}

【背】关键代码:

一维前缀和

预处理:s[i]=a[i]+a[i-1] //前缀和数组
求区间[l,r]:sum=s[r]-s[l-1] //求区间和

二维前缀和

s[x][y] = s[x - 1][y] + s[x][y -1] - s[x -1][y-1] + a[x][y] //二维前缀和数组`
s = s[x2][y2] - s[x1 - 1][y2] - s[x2][y1 - 1] + s[x1 - 1][y1 -1]//`计算子矩阵的和

一维差分

b [ i ] = a [ i ] − a [ i − 1 ]
   s[l]+=c;s[r+1]-=c;// 在原数组中将区间[l, r]加上c

二维差分

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;
}insert(i, j, i, j, a[i][j]);      //构建差分数组insert(x1, y1, x2, y2, c);       //子矩阵加c
b[i][j] += b[i - 1][j] + b[i][j - 1] - b[i - 1][j - 1];  //二维前缀和

相关文章:

【算法笔记】前缀和与差分

第一课前缀和与差分 算法是解决问题的方法与步骤。 在看一个算法是否优秀时&#xff0c;我们一般都要考虑一个算法的时间复杂度和空间复杂度。 现在随着空间越来越大&#xff0c;时间复杂度成为了一个算法的重要指标&#xff0c;那么如何估计一个算法的时间复杂度呢&#xf…...

python实战应用讲解-【实战应用篇】函数式编程-八皇后问题(附示例代码)

目录 知识储备-迭代器相关模块 itertools 模块 创建新的迭代器 根据最短输入序列长度停止的迭代器...

【Servlet篇】如何解决Request请求中文乱码的问题?

前言 前面一篇文章我们探讨了 Servlet 中的 Request 对象&#xff0c;Request 请求对象中封装了请求数据&#xff0c;使用相应的 API 就可以获取请求参数。 【Servlet篇】一文带你读懂 Request 对象 也许有小伙伴已经发现了前面的方式获取请求参数时&#xff0c;会出现中文乱…...

SpringBoot:SpringBoot简介与快速入门(1)

SpringBoot快速入门1. SpringBoot简介2. SpringBoot快速入门2.1 创建SpringBoot项目&#xff08;必须联网&#xff0c;要不然创建失败&#xff0c;在模块3会讲到原因&#xff09;2.2 编写对应的Controller类2.3 启动测试3. Spring官网构建工程4. SpringBoot工程快速启动4.1 为什…...

RabbitMQ学习(十一):RabbitMQ 集群

一、集群1.1 为什么要使用集群前面我们介绍了如何安装及运行 RabbitMQ 服务&#xff0c;不过这些是单机版的&#xff0c;无法满足目前真实应用的 要求。如果 RabbitMQ 服务器遇到内存崩溃、机器掉电或者主板故障等情况&#xff0c;该怎么办&#xff1f;单台 RabbitMQ 服务器可以…...

学渣适用版——Transformer理论和代码以及注意力机制attention的学习

参考一篇玩具级别不错的代码和案例 自注意力机制 注意力机制是为了transform打基础。 参考这个自注意力机制的讲解流程很详细&#xff0c; 但是学渣一般不知道 key&#xff0c;query&#xff0c;value是啥。 结合B站和GPT理解 注意力机制是一种常见的神经网络结构&#xff0…...

网上这么多IT的培训机构,我们该怎么选?

说实话&#xff0c;千万不要把这个答案放在网上来找&#xff0c;因为你只能得到别人觉得合适的或者机构的广告&#xff1b;当然个人的培训经历可以听一听的&#xff0c;毕竟不靠谱的机构也有&#xff0c;比如让你交一两万去上线上课程或者一百号来人坐一起看视频&#xff0c;这…...

数据结构与算法—跳表(skiplist)

目录 前言 跳表 查询时间分析 1、时间复杂度 o(logn) 2、空间复杂度O(n) 动态插入和删除 跳表动态更新 跳表与红黑树比较 跳表实现 前言 二分查找用的数组 链表可不可以实现二分查找呢&#xff1f; 跳表 各方面性能比较优秀的动态数据结构&#xff0c;可以支持快速…...

【C++】5.C/C++内存管理

1.C/C内存管理 int globalVar 1; static int staticGlobalVar 1; void Test() {static int staticVar 1;int localVar 1;int num1[10] {1, 2, 3, 4};char char2[] "abcd";char* pChar3 "abcd";int* ptr1 (int*)malloc(sizeof (int)*4);int* ptr2 …...

一文让你彻底理解关于消息队列的使用

一、消息队列概述 消息队列中间件是分布式系统中重要的组件&#xff0c;主要解决应用解耦&#xff0c;异步消息&#xff0c;流量削锋等问题&#xff0c;实现高性能&#xff0c;高可用&#xff0c;可伸缩和最终一致性架构。目前使用较多的消息队列有ActiveMQ&#xff0c;Rabbit…...

条件期望3

条件期望例题—连续发生的事情 连续地做二项实验, 每一次成功概率为p. 当连续k次成功时, 停止实验. 求停止实验时做的总实验次数的期望. 解: 错误解法 设NkN_kNk​为停止实验时做的总实验次数, 则 E[Nk]E[E[Nk∣Nk−1]]∑jk−1∞E[Nk∣Nk−1j]\begin{split} E[N_k] & E[E…...

第四届蓝桥杯省赛 C++ B组 - 翻硬币

✍个人博客&#xff1a;https://blog.csdn.net/Newin2020?spm1011.2415.3001.5343 &#x1f4da;专栏地址&#xff1a;蓝桥杯题解集合 &#x1f4dd;原题地址&#xff1a;翻硬币 &#x1f4e3;专栏定位&#xff1a;为想参加蓝桥杯的小伙伴整理常考算法题解&#xff0c;祝大家都…...

linux shell 入门学习笔记14 shell脚本+数学计算

概念 把复杂的命令执行过程&#xff0c;通过逻辑代码&#xff0c;组成一个脚本文件的方式就叫做shell脚本。 shebang #! /bin/bash #! /bin/perl #! /bin/python执行脚本的方式 source my_first.sh . my_first.shbash my_first.sh ./my_first.sh变量引用 ${var} 取出变量结果 …...

ESP32设备驱动-MAX30100心率监测传感器驱动

MAX30100心率监测传感器驱动 1、MAX30100介绍 MAX30100 是一款集成脉搏血氧饱和度和心率监测传感器解决方案。 它结合了两个 LED、一个光电探测器、优化的光学器件和低噪声模拟信号处理,以检测脉搏血氧饱和度和心率信号。 MAX30100 采用 1.8V 和 3.3V 电源供电,可通过软件…...

RTD2169芯片停产|完美替代RTD2169芯片|CS5260低BOM成本替代RTD2169方案设计

RTD2169芯片停产|完美替代RTD2169芯片|CS5260低BOM成本替代RTD2169方案设计 瑞昱的RTD2169芯片目前已经停产了&#xff0c; 那么之前用RTD2169来设计TYPEC转VGA方案的产品&#xff0c;该如何生产这类产品&#xff1f;且RTD2169芯片价格较贵&#xff0c;芯片封装尺寸是QFN40&…...

urho3d数据库

只有在启用以下两个构建选项之一时&#xff0c;数据库子系统才会构建到Urho3D库中&#xff1a;Urho3D_Database_ODBC和Urho3D-Database_SQLITE。当两个选项都启用时&#xff0c;URHO3D_DATABASE_ODBC优先。这些构建选项决定子系统将使用哪个数据库API。ODBC DB API更适用于本地…...

141. 周期

Powered by:NEFU AB-IN Link 文章目录141. 周期题意思路代码141. 周期 题意 一个字符串的前缀是从第一个字符开始的连续若干个字符&#xff0c;例如 abaab 共有 5个前缀&#xff0c;分别是 a&#xff0c;ab&#xff0c;aba&#xff0c;abaa&#xff0c;abaab。 我们希望知道一…...

Windows下命令执行绕过技巧总结(渗透测试专用)

一、连接符1、双引号不要求双引号闭合举例&#xff1a;"who"a"mi" //闭合的 "who"a"mi //不闭合的2、圆括号必须在两边&#xff0c;不能包括中间的字符。举例&#xff1a;((whoami))3、^符号&#xff08;转译符号&#xff09;不可以在结尾&…...

mindspore的MLP模型(多层感知机)

导入模块 import hashlib import os import tarfile import zipfile import requests import numpy as np import pandas as pd import mindspore import mindspore.dataset as ds from mindspore import nn import mindspore.ops as ops import mindspore.numpy as mnp from …...

【论文极速读】VQ-VAE:一种稀疏表征学习方法

【论文极速读】VQ-VAE&#xff1a;一种稀疏表征学习方法 FesianXu 20221208 at Baidu Search Team 前言 最近有需求对特征进行稀疏编码&#xff0c;看到一篇论文VQ-VAE&#xff0c;简单进行笔记下。如有谬误请联系指出&#xff0c;本文遵循 CC 4.0 BY-SA 版权协议&#xff0c;…...

C++初阶-list的底层

目录 1.std::list实现的所有代码 2.list的简单介绍 2.1实现list的类 2.2_list_iterator的实现 2.2.1_list_iterator实现的原因和好处 2.2.2_list_iterator实现 2.3_list_node的实现 2.3.1. 避免递归的模板依赖 2.3.2. 内存布局一致性 2.3.3. 类型安全的替代方案 2.3.…...

【kafka】Golang实现分布式Masscan任务调度系统

要求&#xff1a; 输出两个程序&#xff0c;一个命令行程序&#xff08;命令行参数用flag&#xff09;和一个服务端程序。 命令行程序支持通过命令行参数配置下发IP或IP段、端口、扫描带宽&#xff0c;然后将消息推送到kafka里面。 服务端程序&#xff1a; 从kafka消费者接收…...

Java 语言特性(面试系列1)

一、面向对象编程 1. 封装&#xff08;Encapsulation&#xff09; 定义&#xff1a;将数据&#xff08;属性&#xff09;和操作数据的方法绑定在一起&#xff0c;通过访问控制符&#xff08;private、protected、public&#xff09;隐藏内部实现细节。示例&#xff1a; public …...

基于服务器使用 apt 安装、配置 Nginx

&#x1f9fe; 一、查看可安装的 Nginx 版本 首先&#xff0c;你可以运行以下命令查看可用版本&#xff1a; apt-cache madison nginx-core输出示例&#xff1a; nginx-core | 1.18.0-6ubuntu14.6 | http://archive.ubuntu.com/ubuntu focal-updates/main amd64 Packages ng…...

大语言模型(LLM)中的KV缓存压缩与动态稀疏注意力机制设计

随着大语言模型&#xff08;LLM&#xff09;参数规模的增长&#xff0c;推理阶段的内存占用和计算复杂度成为核心挑战。传统注意力机制的计算复杂度随序列长度呈二次方增长&#xff0c;而KV缓存的内存消耗可能高达数十GB&#xff08;例如Llama2-7B处理100K token时需50GB内存&a…...

论文阅读笔记——Muffin: Testing Deep Learning Libraries via Neural Architecture Fuzzing

Muffin 论文 现有方法 CRADLE 和 LEMON&#xff0c;依赖模型推理阶段输出进行差分测试&#xff0c;但在训练阶段是不可行的&#xff0c;因为训练阶段直到最后才有固定输出&#xff0c;中间过程是不断变化的。API 库覆盖低&#xff0c;因为各个 API 都是在各种具体场景下使用。…...

嵌入式常见 CPU 架构

架构类型架构厂商芯片厂商典型芯片特点与应用场景PICRISC (8/16 位)MicrochipMicrochipPIC16F877A、PIC18F4550简化指令集&#xff0c;单周期执行&#xff1b;低功耗、CIP 独立外设&#xff1b;用于家电、小电机控制、安防面板等嵌入式场景8051CISC (8 位)Intel&#xff08;原始…...

阿里云Ubuntu 22.04 64位搭建Flask流程(亲测)

cd /home 进入home盘 安装虚拟环境&#xff1a; 1、安装virtualenv pip install virtualenv 2.创建新的虚拟环境&#xff1a; virtualenv myenv 3、激活虚拟环境&#xff08;激活环境可以在当前环境下安装包&#xff09; source myenv/bin/activate 此时&#xff0c;终端…...

PH热榜 | 2025-06-08

1. Thiings 标语&#xff1a;一套超过1900个免费AI生成的3D图标集合 介绍&#xff1a;Thiings是一个不断扩展的免费AI生成3D图标库&#xff0c;目前已有超过1900个图标。你可以按照主题浏览&#xff0c;生成自己的图标&#xff0c;或者下载整个图标集。所有图标都可以在个人或…...

13.10 LangGraph多轮对话系统实战:Ollama私有部署+情感识别优化全解析

LangGraph多轮对话系统实战:Ollama私有部署+情感识别优化全解析 LanguageMentor 对话式训练系统架构与实现 关键词:多轮对话系统设计、场景化提示工程、情感识别优化、LangGraph 状态管理、Ollama 私有化部署 1. 对话训练系统技术架构 采用四层架构实现高扩展性的对话训练…...