学习笔记:前缀和与差分

1、前缀和(一维,二维)

应用:
一维:快速求一段连续子序列的和
二维:快速求一个子矩阵的和

//一维前缀和
const int N = 1e5+5;
int n,q,a[N],s[N];//a是原数组,s是前缀和数组

int main()
{
    
    
	cin>>n>>q;
	for(int i=1;i<=n;i++)	cin>>a[i], s[i]=s[i-1]+a[i];
	while(q--)//q次询问
	{
    
    
		int l,r;
		cin>>l>>r;
		cout<<s[r]-s[l-1]<<endl;//计算区间[l,r]的和
	}
	return 0;
}
//二维前缀和
const int N = 1e3+5;
int n,m,q,a[N][N],s[N][N];

int main()
{
    
    
	cin>>n>>m>>q;
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++)
		{
    
    
			cin>>a[i][j];
			s[i][j]=s[i][j-1]+s[i-1][j]-s[i-1][j-1]+a[i][j];
		}
		
	while(q--)//q次询问
	{
    
    
		int x1,y1,x2,y2;
		cin>>x1>>y1>>x2>>y2;
		cout<<s[x2][y2]-s[x2][y1-1]-s[x1-1][y2]+s[x1-1][y1-1]<<endl;//计算以(x1,y1)为左上角,(x2,y2)为右下角的子矩阵的和
	}
	return 0;
}

2、差分(一维,二维)

应用:
一维:对于数组中[l,r]快速进行修改操作
二维:对于子矩阵快速进行修改操作

//一维差分
const int N = 1e5+5;

int n,q,a[N],diff[N];//diff差分数组

int main()
{
    
    
	cin>>n>>q;
	//构造差分数组
	for(int i=1;i<=n;i++)	cin>>a[i],diff[i]=a[i]-a[i-1];
	
	while(q--)//q次修改操作
	{
    
    
		int l,r,c;
		cin>>l>>r>>c;
		//此处操作等价于将区间[l,r]内每个数加c
		diff[l]+=c;
		diff[r+1]-=c;
	}
	//由差分数组求原数组
	for(int i=1;i<=n;i++)	a[i]=diff[i]+a[i-1];
	for(int i=1;i<=n;i++)	cout<<a[i]<<" ";cout<<endl;
	return 0;
}

//二维差分
const int N = 1e3+5;

int n,m,q,a[N][N],diff[N][N];

int main()
{
    
    
	cin>>n>>m>>q;
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++)//构造差分数组
			cin>>a[i][j], diff[i][j]=a[i][j]-a[i-1][j]-a[i][j-1]+a[i-1][j-1];
			
	while(q--)//q次修改操作
	{
    
    
		int x1,y1,x2,y2,c;
		cin>>x1>>y1>>x2>>y2>>c;
		//差分数组的子矩阵修改操作,等价与将以(x1,y2)为左上角,(x2,y2)为右下角的每一个数加上c
		diff[x1][y1]+=c;
		diff[x1][y2+1]-=c;
		diff[x2+1][y1]-=c;
		diff[x2+1][y2+1]+=c;
	}
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++)//由差分数组求原数组
			a[i][j]=a[i][j-1]+a[i-1][j]-a[i-1][j-1]+diff[i][j];
	for(int i=1;i<=n;i++)
	{
    
    
		for(int j=1;j<=m;j++)	cout<<a[i][j]<<" ";
		cout<<endl;
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/m0_50815157/article/details/113463758
今日推荐