【模板】前缀和与差分

小问题

有一个长度为 N N N 的序列 A A A,求 A A A 的指定区间内的和。

前缀和

首先,我们将 s u m x sum_x sumx 表示为 ∑ i = 1 x a i \sum_{i=1}^xa_i i=1xai,可知 s u m sum sum 序列是可以 O ( N ) O(N) O(N) 求的。
接下来,对于每组 l , r l,r l,r,显然 ∑ i = l r a i = ∑ i = 1 r a i − ∑ i = 1 l − 1 a i = s u m r − s u m l − 1 \sum_{i=l}^ra_i=\sum_{i=1}^ra_i-\sum_{i=1}^{l-1}a_i=sum_r-sum_{l-1} i=lrai=i=1raii=1l1ai=sumrsuml1
妈呀这不是小学生容斥吗???
在这里插入图片描述

二维前缀和

顾名思义,二维前缀和就是求子矩阵元素和。
同理,我们将 s u m x , y sum_{x,y} sumx,y 表示为 ∑ i = 1 x ∑ j = 1 y a i , j \sum_{i=1}^x\sum_{j=1}^ya_{i,j} i=1xj=1yai,j,又可知 s u m sum sum 序列是可以 O ( N 2 ) O(N^2) O(N2) 求的。
什么,你说不会。好吧,可知 s u m i , j = a i , j + s u m i − 1 , j + s u m i , j − 1 − s u m i − 1 , j − 1 sum_{i,j}=a_{i,j}+sum_{i-1,j}+sum_{i,j-1}-sum_{i-1,j-1} sumi,j=ai,j+sumi1,j+sumi,j1sumi1,j1
妈呀这不又又是小学生容斥吗???
在这里插入图片描述

和预处理一样,对于每组 x 1 , y 1 , x 2 , y 2 x1,y1,x2,y2 x1,y1,x2,y2,显然 ∑ i = x 1 x 2 ∑ j = y 1 y 2 a i , j = s u m x 2 , y 2 − s u m x 2 , y 1 − 1 − s u m x 1 − 1 , y 2 + s u m x 1 − 1 , y 1 − 1 \sum_{i=x1}^{x2}\sum_{j=y1}^{y2}a_{i,j}=sum_{x2,y2}-sum_{x2,y1-1}-sum_{x1-1,y2}+sum_{x1-1,y1-1} i=x1x2j=y1y2ai,j=sumx2,y2sumx2,y11sumx11,y2+sumx11,y11
妈呀这不又又又又是小学生容斥吗???
在这里插入图片描述

差分

我们将 c i c_i ci 记为 a i + 1 − a i a_{i+1}-a_i ai+1ai,会发现一个好玩的性质: ∑ i = 0 x − 1 c i = a x \sum_{i=0}^{x-1}c_i=a_x i=0x1ci=ax
证:
c 0 + c 1 + c 2 + . . . + c x − 1 = a 1 + ( a 2 − a 1 ) + ( a 3 − a 2 ) + . . . + ( a x − a x − 1 ) = a x c_0+c_1+c_2+...+c_{x-1}\\ =a_1+(a_2-a_1)+(a_3-a_2)+...+(a_x-a_{x-1})\\ =a_x c0+c1+c2+...+cx1=a1+(a2a1)+(a3a2)+...+(axax1)=ax
差分这个方法在区间减法很有用。把 l l l r r r 这个区间的数同时减 x x x,那么 c[l-1]-=x,c[r]+=x
在这里插入图片描述
你在期待代码吗,好的。

//前缀和
for(int i=1;i<=n;i++) sum[i]=sum[i-1]+a[i];
int get(int l,int r){
	return sum[r]-sum[l-1];
}
//二维前缀和
for(int i=1;i<=n;i++){
	for(int j=1;j<=m;j++){
		sum[i][j]=a[i][j]+sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1];
	}
}
int get(int x,int y,int xx,int yy){
	return sum[xx][yy]-sum[x-1][yy]-sum[xx][y-1]+sum[x-1][y-1];
}
//差分
for(int i=1;i<=n;i++){
	c[i]=a[i]-a[i-1];
}
void update(int l,int r,int x){
	c[l-1]-=x,c[r]+=x;
}
  • 7
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值