差分与前缀和学习笔记
本来是不想写这篇博客的,但为了课前十分钟还是来水一发
前缀和
简介
继续引用OI-Wiki的话(OI-Wiki
前缀和可以简单理解为「数列的前
项的和」,是一种重要的预处理方式,能大大降低查询的时间复杂度。
也就是说,我们能使用
为什么要使用前缀和?
假如我们有一段长为
那么怎么做?
假设给出的数列为
那么显然,如果我们要求出从第
而
示范代码如下:
cin >> n >> q;
for (int i = 1; i <= n; i++){
cin >> a[i];
sum[i] = a[i] + sum[i - 1];
}
while(q--){
cin >> l >> r;
cout << sum[r] - sum[l - 1] << endl;
}
扩展:二维前缀和
前面我们的讨论都是在一个一位的数列上进行的,但如果题目给我们的是一个二维的矩阵,阁下又当如何应对?
显然的,我们同样可以构造一个矩阵
首先,我们要加上
如下图所示。我们要计算整块前缀和,就要先加上右下角这些,再加上左侧的所有前缀和和上面的前缀和。这时你会发现,我们把左上角的那一部分算了两次,于是我们减掉一次就好了。
那么怎么查询特定块的前缀和呢?
再看下面这张图。我们现在要计算红色部分的前缀和,而红色部分的前缀和等于总的前缀和
下面是示范代码:
// 处理前缀和
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++)
sum[i][j] = sum[i - 1][j] + sum[i][j - 1] - sum[i - 1][j - 1] + a[i][j];
// 查询前缀和
while(q --){
int l1, r1, l2, r2;
cin >> l1 >> r1 >> l2 >> r2;
cout << sum[l2][r2] - sum[l1 - 1][r2] - sum[l2][r1 - 1] + sum[l1 - 1][r1 - 1] << endl;
}
差分
简介
再次引用OI-Wiki的话:
差分是一种和前缀和相对的策略,可以当做是求和的逆运算。
用人话来说,差分支持我们通过前缀和的方式,实现
为什么要使用差分
同理,使用差分可以避免对数列中每个元素的值一个一个进行修改,使得程序的运行时间大大减少。
那么怎么做?
针对给出的数列
那么我们可以得出这样的一个式子:
但这样显然没有任何优势,但是差分的优势在于对区间元素的修改。假如我们要给
解释以下。根据差分的定义,给
示范代码如下:
cin >> n >> q;
for (int i = 1; i <= n; i++){
cin >> a[i];
b[i] = a[i] - a[i - 1];
}
while(q--){
cin >> l >> r >> val;
b[l] += val;
b[r + 1] -= val;
}
for (int i = 1; i <= n; i++){
sum[i] = sum[i - 1] + b[i];
cout << sum[i] << ' ';
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】