基础算法第三期 前缀和及差分(一维+二维)

文章目录


前言

前缀和及其差分十分重要在算法竞赛中经常用到,希望大家通过本篇文章的学习能够熟练掌握并且运用

一、(一维前缀和及其差分)

(1)一维前缀和(典型例题及其AC代码讲解)

一维前缀和公式:

#include<iostream>
using namespace std;
#include<vector>
#include<algorithm>
const int N=1e5+10;
int n,m,sum[N],a[N];
int main()
{
	cin>>n>>m;
	int nn;
	sum[0]=0;
	for(int i=1;i<=n;i++){
		cin>>a[i];
		sum[i]=sum[i-1]+a[i];//这里将a数组的前n项和储存起来,即该公式即为一维前缀和
	}
	int l,r;
	while(m--){
		cin>>l>>r;
	    int maxs=max(l,r);//在这里需要判断一下大小关系
		int mini=min(l,r);
		cout<<sum[maxs]-sum[mini-1]<<endl;//这里直接求出即可
	}
	return 0;
}

(2)一维差分

一维差分公式:

该公式中x代表左边界,y代表右边界,z改变量,由前缀和的性质可知只需对边界进行处理即可,也就是说可以另取一个数组b进行操作在将各个区间最终的操作加起来之后,在加入到原数组当中

下面给出例题

#include<iostream>
using namespace std;

const int N=1e5+7;
int n,m,a[N],b[N],l,r,c;

void add(int x,int y,int z)//差分公式
{
	b[x]+=z;
	b[y+1]-=z;
}
int main()
{
    cin>>n>>m;
	for(int i=1;i<=n;i++){
		cin>>a[i];
	}
	while(m--){
		cin>>l>>r>>c;
		add(l,r,c);
	}
	for(int i=1;i<=n;i++){
		b[i]+=b[i-1];//对每一个数最终的操作
	}
	for(int i=1;i<=n;i++){
		a[i]+=b[i];//将最终的操作加到原数组当中
	}
	for(int i=1;i<=n;i++){
	    cout<<a[i]<<" ";
	}
	return 0;
}

二、二维前缀和及其差分

(1)二维前缀和

二维前缀和公式:

#include<iostream>
using namespace std;

const int N=1e3+10;
int n,m,q;
int a[N][N],sum[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];
			sum[i][j]=sum[i-1][j]+sum[i][j-1]+a[i][j]-sum[i-1][j-1];//二维前缀和公式
		}
	}
	int x1,y1,x2,y2;
	while(q--){
		cin>>x1>>y1>>x2>>y2;
		cout<<sum[x2][y2]-sum[x1-1][y2]-sum[x2][y1-1]+sum[x1-1][y1-1]<<endl;
	}
	return 0;
}

(2)二维差分

二维差分公式:


tx1,ty1是起始位置,tx2,ty2,是结束的位置,c是改变量,二维差分其实用到的不算太多,不过也尽量理解着记下来,万一哪天要考到了呢

#include<iostream>
using namespace std;

const int N=1e3+10;
int a[N][N],b[N][N],sum[N][N];
int y1,x1,x2,y2,c,n,m,q;

void add(int tx1,int ty1,int tx2,int ty2,int c)//二维差分公式
{
	b[tx1][ty1]+=c;
	b[tx1][ty2+1]-=c;
	b[tx2+1][ty1]-=c;
	b[tx2+1][ty2+1]+=c;
}


int main()
{
	cin>>n>>m>>q;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			cin>>a[i][j];
		}
	}
	while(q--){
		cin>>x1>>y1>>x2>>y2>>c;
		add(x1,y1,x2,y2,c);
	}
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			b[i][j]+=b[i][j-1]+b[i-1][j]-b[i-1][j-1];//其实该操作与一维操作理解差不多,不过是复杂了一些,该操作相当于求每一个数的改变量
		}
	}
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			a[i][j]+=b[i][j];//将每一个数的改变量加入到原数组当中
		}
	}
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			cout<<a[i][j]<<" ";
		}
		cout<<endl;
	}
	return 0;
}

总结

以上就是我对该部分的理解,希望大家多多建议,谢谢大家,同时作为小白也希望能够与大家共同进步,感谢大家的观看!!!

  • 24
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值