前缀和&差分算法

前言

2023.1.9 重学了前缀和与差分算法,特此写一篇小博客。

前缀和

应用场景

多次求区间和

算法描述

Σ Σ Σf[i] = a [ i ] + f [ i − 1 ] = a[i]+f[i-1] =a[i]+f[i1]
非常的好理解,字面意思

代码实现

#include<bits/stdc++.h>
using namespace std;

const int maxn=1e3+10;
int n,q;
int a[maxn],f[maxn];
int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++){
		scanf("%d",&a[i]);
		f[i]=f[i-1]+a[i];//求每一位的前缀和
	}
	//q次查询
	scanf("%d",&q);
	while(q--){
		int l,r;
		scanf("%d%d",&l,&r);
		printf("%d\n",f[r]-f[l-1]);//区间和输出
	}
	return 0;
} 

差分

应用场景

多次进行区间修改

算法描述

差分算法主要是前缀和算法来支持的一个算法

假设我们要把 a [ l ]   a [ r ] ( 包括 a [ l ] 和 a [ r ] ) 同一加上一个 x a[l]~a[r](包括a[l]和a[r])同一加上一个x a[l] a[r](包括a[l]a[r])同一加上一个x 如何便捷实现?

我们先想一个最朴素的办法,直接 f o r ( i n t i = l ; i < = r ; i + + ) a [ i ] + = x ; for(int i=l;i<=r;i++)a[i]+=x; for(inti=l;i<=r;i++)a[i]+=x;循环一遍,时间复杂度为 O ( n ) O(n) O(n),如果进行过多次的修改,时间复杂度直接爆了,所以需要优化

差分算法诞生了

  1. 定义一个新的数组 b [ ] b[] b[]
  2. a [ i ] − a [ i − 1 ] ( 1 ≤ i ≤ n ) a[i]-a[i-1](1≤i≤n) a[i]a[i1](1in)的值记录在 b [ i ] b[i] b[i]
  3. 进行修改操作,使 b [ l ] + = x , b [ r + 1 ] − = x b[l]+=x,b[r+1]-=x b[l]+=x,b[r+1]=x
  4. 待所有修改操作完成后求一遍前缀和(巧妙抵消),回得到新的 a [ 1 ] … … a [ n ] a[1]……a[n] a[1]……a[n]

代码实现

#include<bits/stdc++.h>
using namespace std;

const int maxn=1e3+10;
int n,q;
int a[maxn],b[maxn];
int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++){
		scanf("%d",&a[i]);
		b[i]=a[i]-a[i-1];//求差
	} 
	//q次修改操作
	scanf("%d",&q);
	while(q--){
		int l,r,x;
		scanf("%d%d%d",&l,&r,&x);
		//修改
		b[l]+=x;
		b[r+1]-=x;
	}
	//求b[]前缀和《=》a[]修改后的形式
	for(int i=1;i<=n;i++)a[i]=a[i-1]+b[i];
	//输出新数组a[]
	for(int i=1;i<=n;i++)printf("%d ",a[i]);
	printf("\n");
	return 0;
} 

补充

有时前缀和会与差分结合

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

materialistOier

我只是一名ssfoier

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值