目录
前言
差分算法是一种处理数字序列或函数的方法,其主要思想是通过对序列中的元素进行差分运算来获取序列的性质。这种算法在许多领域都有应用,包括计算机科学、数据分析、信号处理等。
在计算机科学中,差分算法通常用于解决动态规划问题。通过将原始问题分解为更小的子问题,并利用子问题的解来构造原问题的解,差分算法可以有效地降低问题的复杂度。
差分是前缀和的逆运算,它们之间的关系就好比积分和求导。它们都是一种小技巧,在算法比赛中使用广泛。
一、模板
1.一维差分讲解
一维差分,顾名思义,就是对一维数组(线性数组)中相邻元素的差值进行计算的一种方法。一维差分的公式如下: 假设我们有一个一维数组A,长度为n,其元素为
我们想要计算其差分数组D,其中为和的差值,即。 差分数组D的长度也是n,其元素为
根据差分的定义,我们可以得到以下公式:
1. 如果i == 0,那么
2. 如果i > 0,那么
差分数组D的生成过程可以概括为:
1. 初始化
2. 对于i从1到n-1,计算这就是一维差分的基本公式。
通过差分,我们可以更方便地分析和处理一维数组。
2.差分模板
void insert(int l,int r,int k){
b[l]+=k;
b[r+1]-=k;
}
3.差分模板讲解
这段代码是一个C++函数,名为`insert`,它接受三个参数:整数`l`、整数`r`和整数`k`。该函数的功能是在数组的`l`位置插入一个值为`k`的元素,然后在`r+1`位置删除一个值为`k`的元素。
这段代码的主要操作是在差分数组`b`上进行的。差分数组`b`与原数组`a`的关系为:
其中,a[i]是原数组中的第i个元素,b[i]是差分数组中对应的元素。
现在,让我们分析一下`insert`函数中的操作:
1. :在差分数组`b`的第`l`个位置加上`k`,相当于在原数组的`l`位置插入一个值为`k`的元素,并保持其他位置的元素值不变。
2. :在差分数组`b`的第`r+1`个位置减去`k`,相当于在原数组的`r+1`位置删除一个值为`k`的元素,并保持其他位置的元素值不变。 通过这种方式,我们可以在不修改原数组的情况下,在指定位置插入或删除元素。
了解思想了吧,快去下面习题想想怎么做吧!
二、习题
1.题目来源
P2367 语文成绩 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
2.题目描述:
3.题目讲解:
根据题目,给区间的元素加上z,可知此题要利用差分来写。代码讲解中,有详细解释利用模板。
4.完整代码:
#include<bits/stdc++.h>
using namespace std;
const int N=5e6+10;
int a[N],b[N];
void insert(int l,int r,int k){
b[l]+=k;
b[r+1]-=k;
}
int main(){
int n,p,c=1e10;
cin>>n>>p;
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
for(int i=1;i<=n;i++) insert(i,i,a[i]);
while(p--){
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
insert(x,y,z);
}
for(int i=1;i<=n;i++){
b[i]+=b[i-1];
if(b[i]<c) c=b[i];
}
cout<<c<<endl;
return 0;
}
5.代码讲解:
差分数组构造:
for(int i=1;i<=n;i++) insert(i,i,a[i]);
差分数组b与原数组a的关系是:。也就是说,b[i]是原数组中第i个元素与第i-1个元素之差。
因此,当我们调用时,实际上是在差分数组b的i
位置插入了,在i+1
位置插入了。这样,原数组a的每个元素都被插入到差分数组b中,从而得到差分数组b。
利用差分数组实现x-y区间加上z的操作:
while(p--){
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
insert(x,y,z);
}
实现题目全部操作后数组a的全部元素大小并找出最小值:
for(int i=1;i<=n;i++){
b[i]+=b[i-1];
if(b[i]<c) c=b[i];
}
等于操作实现后的数组元素大小,原因:
因为,所以实际上,。
因此,差分序列的累加和,即,正好等于原数组的大小。
讲解结束啦,谢谢观看!
总结
差分是一个比较好用的技巧,在算法比赛中,常常要考到。
呃呃呃?要不给作者一个赞和收藏,嘿嘿,在顺手点个关注?(有些厚颜无耻了)
感谢友友们交流,以及欢迎友友们评论!非常感谢大家阅读!让我们一起努力学习算法吧。
代码能力是练习出来的,不是看出来的,快去练习!!!