前缀和
·一维前缀和
对于一维数组来说,前缀和就是前n项和,s[i]=a[1]+a[2]+...+a[i-1]+a[i];
对于给一个询问区间[l,r]内的和,我们只需要预处理出前缀和(O(n)),然后输出s[r]-s[l-1](O(1)),这样达到减少一层循环暴力加法的时间。
一维前缀和原理
s[r]=a[1]+a[2]+...+a[l-1]+a[l]+...+a[r-1]+a[r];
s[l-1]=a[1]+a[2]+...+a[l-1];
作差法得到区间[l,r]内的和为s[r]-s[l-1]
·二维前缀和
对于二维数组,s[i][j]表示的是从左上角[1][1]到[i][j]矩阵的和,注意会有重复的,s[i][j]的取法不一样。
对于给一个询问矩阵[x1,y1]到[x2][y2]之间的和,我们可以用
来表示
二维前缀和预处理O(nm),查询O(1)
二维前缀和原理
中间会有重复的部分,跟我们以前做一种题目一样,一个班上打羽毛球有x人,踢足球有y人,同时会打羽毛球和踢足球的有z人...
差分
概念&用途
前缀和是自身加上前一个,而差分就是自身减去前一个,与前缀和类似于一个“逆运算”,我们维护的是两个相邻数的差
用途的话,我们可以给一个区间[l,r]全部加上k,我们可以在差分数组中将b[r+1]-=k,b[l]+=k;这样最后再扫一遍求和(前缀和)求得的就是最后所有区间加得的一个数组a
·一维差分
想要给定一个区间[l,r]内全部加上k,我们循环是O(n),但是我们只需要b[r+1]-=k,b[l]+=k;进而达到O(1) 的处理
b数组是我们差分而来的,b[i]=a[i]-a[i-1];
一维差分原理
想要区间[l,r]全部加上k,也就是a[l]+=k,a[l+1]+=k...a[r]+=k,但是我们只需要在差分数组b[l]+=k,b[r+1]-=k;也就是说,我们最后求前缀和时候,在b[l]上加的k会一直由于前缀和加前一个而达到后面,但是在b[r+1]上减去的k就发挥其作用,导致后面的在加上k的基础上再减去k(不会加上k)
举例
举出a[i]={1,2,3,4,4,5}的例子,得到差分数组b[i]={1,1,1,1,0,1}(也就是当前减前一个)
然后我们在区间[2,5]加上5,那么b[5+1]-=5,b[2]+=5;我们得到b[i]={1,6,1,1,0,-4}
现在还原a数组,就得求一次前缀和,得到a[i]={1,7,8,9,9,5},也就相当于在区间[2,5]上加上5
·二维差分
预处理
区间修改操作
b[x1][ y1 ] +=c ; 对应图1 ,让整个a数组中蓝色矩形 面积的元素都加上了c。
b[x1][y2+1]-=c ; 对应图2 ,让整个a数组中绿色矩形 面积的元素再减去c,使其内元素不发生改变。
b[x2+1][y1]- =c ; 对应图3 ,让整个a数组中紫色矩形 面积的元素再减去c,使其内元素不发生改变。
b[x2+1][y2+1]+=c; 对应图4,让整个a数组中红色矩 形面积的元素再加上c,红色内的相当于被减了两 次,再加上一次c,才能使其恢复
所以只需要 b[x1][y1] += c; b[x1][y2+1] -=c; b[x2+1][y1] -=c; b[x2+1][y2+1] += c;
感谢
感谢郎老师的讲解与PPT,thanks for pengpenglang