前缀和与差分模板

本文详细介绍了前缀和的概念及其在一维和二维数组中的应用,包括如何快速求解矩阵子区域的和。同时,阐述了差分操作与前缀和的逆关系,以及在一维和二维数组中如何进行差分更新和还原原数组。这些算法在解决数组区间操作问题时能显著提高效率。
摘要由CSDN通过智能技术生成

前缀和:一维前缀和:一个数列中某一段的和;
二维前缀和:一个矩阵中某一个子矩阵的和;
一维前缀和:求区间[l,r]中的和,s[r]-s[l-1];s是a的前缀和;
注意事项,读取数组时从1开始,避免判断(即可以用公式统一化)
—————————————————————————————
int a[N],s[N];
int main()
{
for(int i=1;i<=n;i++) cin>>a[i];//读取原数组;
for(int i=1;i<=n;i++) s[i]=s[i-1]+a[i];//初始化前缀和数组;
int l,r;
cin>>l>>r;
cout<<s[r]-s[l-1]<<endl;
return 0;
}
—————————————————————————————
int a[N][N],s[N][N];//原数组和前缀和数组;
二维前缀和:设所求子矩阵的左上角坐标为(x1,y1),右上角为(x2,y2);
则该矩阵的和为:s[x2][y2]-s[x2][y1-1]-s[x1-1][y2]+s[x1-1][y1-1];
—————————————————————————————
int main()
{
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
cin>>a[i][j];//读取前缀和数组;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
s[i][j]=a[i][j]+s[i][j-1]+s[i-1][j]-s[i-1][j-1]//初始化前缀和数组;
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];
return 0;
}
如果有多次询问时可减少时间复杂度;
—————————————————————————————
差分:差分和前缀和互为逆运算,应用于数组某段加一个c或减个c;
一维差分;原数组 1 1 2 3 5;则差分数组为 1 0 1 1 2 -5;差分数组里每一个数等于原数组里对应位置的数剪前一个数,第一个的前一个数为0,最后一个数的后一个数为0;
二维差分同理;
差分数组里前n项的和等于原数组里的第n项;
—————————————————————————————
一维差分模板:
int a[N],b[N]//定义原数组和差分数组;
void insert(int l,int r,int c)
{
b[l]+=c;
b[r+1]-=c
}
int main()
{
int n;
for(int i=1;i<=n;i++)
cin>>a[i];读取原数组;
for(int i=1;i<=n;i++)
intsert(i,i,a[i]);将原数组变成差分数组;
intt ,l,r,c;cin>>l>>r>>c;
insert(l,r,c);
for(int i=1;i<=n;i++) b[i]+=b[i-1];//得到目标数组;
for(int i=1;i<=n;i++) cout<<b[i];
return 0;
}
—————————————————————————————
二维差分模板:
int a[N][N],b[N][N];定义原数组和差分数组;
void (int x1,int y1,int x2,int y2,int c)
{
b[x1][y1]+=c;
b[x2+1][y1]-=c;
b[x1][y2+1]-=c;
b[x2+1][y2+1]+=c;
}
int main()
{
int n,m;cin>>n>>m;
for(int i=1;i<=n;i++)
for(int j=1;i<=m;j++)
cin>>a[i][j];//读取原数组;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
insert(i,j,i,j,a[i][j]);构造原数组的差分数组;
int x1,y1,x2,y2,c;
cin>>x1>>y1>>x2>>y2>>c;
insert(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++)
cout<<b[i][j]<<" “;
puts(”");
}
return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值