二维前缀和与差分的小总结

什么是差分。

给你一串长度为n的数列a1,a2,a3…an,要求对a[L]~a[R]进行m次操作:

操作一:将a[L]~a[R]内的元素都加上P

操作二:将a[L]~a[R]内的元素都减去P

最后再给出一个询问求a[L]-a[R]内的元素之和?

差分就该派上用场了,我们新开一个数组b,储存每一次的修改操作,最后求前缀和的时候统计一下就能快速的得到正确答案了,详细请看下面代码。

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+9;
int a[maxn],b[maxn];
int main(){
	int i,j,k,n,m,p;
	cin>>n>>m;
	for(i=1;i<=n;i++){
		cin>>a[i];
	}
	for(i=1;i<=m;i++){
		int L,R,t;
		cin>>t>>L>>R>>p;
		if(t==1){
			b[L]+=p;b[R+1]-=p; 
		}
		else{
			b[L]-=p;b[R+1]+=p;
		}
	}
	int add=0;
	for(i=1;i<=n;i++){
		add+=b[i];
		a[i]+=a[i-1]+add;
	}
	int x,y;
	cin>>x>>y;
	cout<<a[y]-a[x-1]<<endl;
}

讲解二维前缀和吧。

给定一个n*m大小的矩阵a,有q次询问,每次询问给定x1,y1,x2,y2四个数,求以(x1,y1)为左上角坐标和(x2,y2)为右下角坐标的子矩阵的所有元素和。注意仍然包含左上角和右下角的元素。

在这里插入图片描述


	a[i][j]+=a[i][j-1]+a[i-1][j]-a[i-1][j-1];

为方便理解贴个图
在这里插入图片描述

假如我想求a[2][4]的前缀和,我得先加上a[1][4]的前缀和,再加上a[2][3]的前缀和,然后这个时候我们发现实际上a[1][3]这个部分我们加了两遍,所以我们需要再减去一遍a[1][3],于是得出公式a[i][j]+=a[i][j-1]+a[i-1][j]-a[i-1][j-1]。

接下来看完整代码吧。

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e3+9;
int a[maxn][maxn];
int main(){
	int i,j,k,n,m,q;
	cin>>n>>m>>q;
	for(i=1;i<=n;i++){
		for(j=1;j<=m;j++)
		cin>>a[i][j];
	}
	for(i=1;i<=n;i++){
		for(j=1;j<=m;j++)
		a[i][j]+=a[i][j-1]+a[i-1][j]-a[i-1][j-1];
	}
	for(i=1;i<=q;i++){
		int x1,y1,x2,y2;
		cin>>x1>>y1>>x2>>y2;
		int ans=a[x2][y2]-a[x1-1][y2]-a[x2][y1-1]+a[x1-1][y1-1];
		cout<<ans<<endl;
	}
}

     cin>>x1>>y1>>x2>>y2>>p;
     b[x1][y1]+=p;b[x2+1][y2+1]+=p;
     b[x2+1][y1]-=p;b[x1][y2+1]-=p;

猜你喜欢

转载自www.cnblogs.com/xcfxcf/p/12354678.html