[算法篇] 简单讲讲一维前缀和与差分
前缀和:
先给定义:指某序列的前n项和
是不是与我们高中所学的数列求和类似?
给出用途:
如我们于一组长度为n的整数序列中询问m次,每次询问中输出区间[l,r]中数之和
倘若我们先不使用前缀和,预测一下思路将会是:m次询问中,每一次都求和数组[l,r]
时间复杂度为O(n),思路很简单但若m非常大则将循环很多次,可想而知这并非较优的办法。
回归数列知识,设数列a[n]的前n项和我们设为S[n]
我们要求a[4]到a[10]之和,则可得a[4]+a[10]=S[10]-S[3]即可
所以前缀和便是令S[r]-S[l-1]
接下来便简单了,贴出代码:(于数组a中求区间[l,r]中之和)
#include<iostream>
using namespace std;
long long a[100000000],arr[100000000];//全局数组默认每一项都为0
int main() {
ios::sync_with_stdio, cout.tie(0), cin.tie(0);//这一行是关闭输入输出流的同步,提高程序运行效率,读者可自行去了解
int m,n;//m为询问次数,n为所需序列长度
cin >> m >> n;
for (int i = 1; i <= n; ++i) {//i从1开始
cin >> a[i];
arr[i] = arr[i - 1] + a[i];
}
while (m--) {
int l, r;
cin >> l >> r;
cout << arr[r] - arr[l - 1] << '\n';
}
return 0;
}
特别注意:我们这里输入时以i=1为首项,是为了后面i-1时不为-1
前缀和具有良好的查询性质,而差分具有良好的修改性质
差分其实便是前缀和的逆运算,可以快速对数组某一区间进行修改操作
我们需要引入一个辅助数组b[n],令b[i]=a[i]-a[i-1](当i=1时,b[1]=a[1]-a[0],a[0]=0)
以下呈现目的:
我们不妨将b[n]中求和b[1]到b[j]
即b[1]+b[2]+b[3].....+b[j]=(a[1]-a[0]) + (a[2]-a[1]) + (a[3]-a[2]) +....+ (a[j]-a[j-1])
所以则等于a[j],这像不像我们高中时常用的裂项求和?
利用这个如何体现出修改的用途呢?
首先:
a[1]=b[1]
a[2]=b[1]+b[2]
a[3]=b[1]+b[2]+b[3]
a[4]=b[1]+b[2]+b[3]+b[4]
a[n]=b[1]+b[2]+b[3]+b[4]+...+b[n]
假设我们想让[3,n]中的数同时+3
则我们只需令b[3]+3,则a[3]往后数的都会同时+3
如:
a[3]+3=b[1]+b[2]+b[3]+3
a[4]+3=b[1]+b[2]+ (b[3]+3) +b[4]
...
那如果只令一小段,如[3,5]中同时+3呢
我们只需令b[3]+3,再让b[6]-3
我们于草稿纸中画出
不难发现a[3]往后同时+3,再让a[6]往后同时-3,则只有a[3]到a[5]进行了+3的修改
这种方法是否比通过循环令原数组挨个修改快速许多?
解决问题:给定一个长度为𝑛的数组𝑎,进行p次区间同时加x的修改,q次区间求和的查询
以下贴上代码:
#include<iostream>
using namespace std;
using ll = long long;
ll a[100000000],arr[10000000],b[100000000];
//考虑可能数据很大所以此处用long long
void insert(int l, int r, int x) {//让数组a[n]在区间[l,r]中同时增加x
b[l] += x;
b[r + 1] -= x;
}
int main() {
ios::sync_with_stdio, cout.tie(0), cin.tie(0);
int n, p, q;
cin >> n >> p >> q;
for (int i = 1; i <= n; ++i) {
cin >> a[i];
b[i] = a[i] - a[i - 1];
}
while (p--) {//p次修改
int l, r, x;
cin >> l >> r >> x;
insert(l, r, x);
}
for (int i = 1; i <= n; ++i){
a[i] = a[i - 1] + b[i];//将b[i] = a[i] - a[i - 1]换下便是此式
arr[i] = arr[i - 1] + a[i];//前缀和
}
while (q--) {//q次询问
int l, r;
cin >> l >> r;
cout << arr[r] - arr[l - 1] << '\n';
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)