前缀和与差分是最基础的算法,也是最简单的算法之一。不过它们是降低时间复杂度的有力算法,利用前缀和或差分进行预处理,往往可以将时间复杂度降低一个n的规模。给定一个数组a[n],设第i个前缀和为s[i],第i个差分为d[i],s[i]就是从第1个元素到第i个元素的数的总和,d[i]就是a[i]-a[i-1]。s[i]=s[i-1]+a[i]。我们容易看出,前缀和与差分互为逆过程。那么,它们有什么用处呢?假如说我们要求一段区间[l,r]之和,按照朴素算法思想,我们需要从区间首加到区间尾部,如果要求m次区间和,复杂度高达O(mn),这显然无法接受,于是我们可以使用前缀和,以O(n)的复杂度预处理出前缀和,之后每次询问只要输出s[r]-s[l-1]即可,时间复杂度降低至O(m+n),可以接受。差分的运用更有意思,假设我们每次对一段区间[l,r]上的所有数据同时进行加减操作,例如同时加上x,求m次的操作之后数组每个的值是多少。按照朴素算法思想,直接对题意进行模拟操作,时间复杂度高达O(mn),无法接受。于是我们想到了差分,我们定义一个差分数组d[n],其中d[i]=a[i]-a[i-1],进行操作时,只需要d[l]+=x,d[r+1]-=x即可,这样可以直接表示出这个操作,最后对差分数组d[i]求前缀和即可得到答案。
先来一道前缀和的例题。
题目描述
小 K 打下的江山一共有n个城市,城市ii和城市i+1有一条双向高速公路连接,走这条路要耗费时间ai。
小 K 为了关心人民生活,决定定期进行走访。他每一次会从1号城市到n号城市并在经过的城市进行访问。其中终点必须为城市n。
不仅如此,他还有一个传送器,传送半径为k,也就是可以传送到i-k和i+k。如果目标城市编号小于1则为1,大于n则为n。
但是他的传送器电量不足,只能传送一次,况且由于一些原因,他想尽量快的完成访问,于是就想问交通部部长您最快的时间是多少。
注意:他可以不访问所有的城市,使用传送器不耗费时间
输入格式
两行,第一行n,k。
第二行n-1个整数,第i个表示ai。
输出格式
一个整数,表示答案。
输入输出样例
输入 #1
4 0
1 2 3
输出 #1
6
总之就是非常简单,找到区间长度为k的区间中区间和最大的,再用总和减去它,就得到了答案。
代码如下
#include<iostream> #include<cstdio> typedef long long ll; const int maxn=(1e6)+5; using namespace std; int n,k; ll a[maxn]; ll sum[maxn]; int main(){ scanf("%d %d",&n,&k); for(int i=1;i<n;i++){ scanf("%lld",&a[i]); sum[i]=sum[i-1]+a[i]; } ll t=0; for(int i=0;i<=n-1-k;i++){ t=max(t,sum[i+k]-sum[i]); } ll ans=sum[n-1]-t; if(k>=n-1)ans=0; printf("%lld\n",ans); return 0; }
再来一道差分的例题
Color the ball
Time Limit: 9000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 45070 Accepted Submission(s): 20817
当N = 0,输入结束。
#include<iostream> #include<cstdio> #include<cstring> using namespace std; const int maxn=100005; int d[maxn],a[maxn]; int main(){ int n; scanf("%d",&n); while(n){ memset(a,0,sizeof(a)); memset(d,0,sizeof(d)); int x,y; int m=n; while(m--){ scanf("%d%d",&x,&y); d[x]+=1; d[y+1]-=1; } for(int i=1;i<n;i++){ a[i]=a[i-1]+d[i]; printf("%d ",a[i]); } a[n]=a[n-1]+d[n]; printf("%d\n",a[n]);//卡格式 scanf("%d",&n); } return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧