前缀和与差分

首先前缀和
前缀和就是一种预处理,用空间来换取时间,降低时间复杂度,它可以非常灵活的面对关于区间的询问。简单点说就是提前计算好前缀和数组sum[i],在后面计算的时候直接使用

原数组a[i] 前缀和数组sum[i]
sum[1] = a[1]
sum[2] = a[1] + a[2] = sum[1] + a[2]
sum[3] = a[1] + a[2] + a[3] = sum[2] + a[3]
sum[4] = a[1] + a[2] + a[3] + a[4] = sum[3] + a[4]
.
.
sum[n] = a[1] + a[2] + …+ a[n] = sum[n-1] + a[n]

for(int i=1;i<=n;i++)
{
	cin >> a[i];
	sum[i] = sum[i-1] + a[i];
}

对于前缀和,最常见的题目就是T次询问,每次给定一个区间[L,R],求区间内序列的和

当然直接暴力跑也不是不可以,但是在数据范围比较大的时候,可能会超时,但是使用前缀和就可以把O(n*m)的复杂度降为O(n)
这样区间[L,R]的和就是sum[r] - sum[l-1]

然后差分
定义一个数组c为差分数组,那么
c[1] = a[1] - a[0]
c[2] = a[2] - a[1]
c[3] = a[3] - a[2]
.
.
c[n] = a[n] - a[n-1]
我们可以看出差分数组其实就是原数组相邻两项之间的差

例如这样一个序列a
0 0 0 0 0
我们要在区间[2,4]中给每个数加上1
那么序列a将要变成
0 1 1 1 0
差分数组c就会变成
0 1 0 0 -1
我们可以发现对原数组的某个区间 [l,r] 值进行改变就相当于对差分数组的元素l,r+1进行改变,即c[l]++,c[r+1]–,这样就把对原数组的区间修改变成了对差分数组的单点修改

for(int i=1;i<=n;i++)	cin >> a[i];
while(T--)
{
	int l,r;
	cin >> l >> r;
	c[l]++,c[r+1]--;
}

我们再看差分数组,这次定义一个数组sum记录差分数组的前缀和
a[0] = 0
c[i] = a[i] - a[i-1]
sum[1] = c[1] = a[1]
sum[2] = c[1] + c[2] = a[2]
sum[3] = c[1] + c[2] + c[3] = a[3]
.
.
sum[n] = c[1] + c[2] + c[3] +…+c[n] = a[n]
我们发现差分数组的前缀和就是原数组,这样就通过前缀和得到了原序列

关于差分最基础的题就是有N个气球排成一排,从左到右依次编号为1,2,3…N.每次给定2个整数a b(a <= b),从气球a开始到气球b依次给每个气球涂一次颜色。求N次以后每个气球被涂过几次色

这个题看明白之后就是求差分的前缀和

int a[maxn],b[maxn];
int n;
int main()
{
	cin >> n;
	for(int i=1;i<=n;i++)
	{
		int l,r;
		cin >> l >> r;
		b[l]++,b[r+1]--; 
	}
	for(int i=1;i<=n;i++)
		a[i] = a[i-1]+b[i];
	for(int i=1;i<n;i++)
		printf("%d ",a[i]);
	printf("%d\n",a[n]);
	return 0;
}
  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

你数过天上的星星吗

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值