一维差分 与 二维差分

一维差分
数组int a[5]={1,3,7,5,2}
前缀和数组a[i]+=a[i-1];
差分数组 d[i]=a[i]-a[i-1]; 差分数组前缀和d[i]+=d[i-1];
差分数组和原数组的关系:
对 差分数组 进行 求 前缀和 得到 原数组

1 3 7 5 2 a[i]
1 2 4 -2 -3 d[i]
1 3 7 5 2 d[i] (sum)

对区间
[0,2]+1
[1,3]-3
[2,4]+5
一般的方法我们是进行for循环,找到特定的位置然后进行运算,
但是这样会浪费太多的时间
这里,我们进行差分标记,我们对差分数组进行运算
a[L1,R1]+1 <=>d[L1]+1,d[R1+1]-1
a[L2,R2]-3 <=>d[L2]-3,d[R2+1]+3
a[L3,R3]+5 <=>d[L3]+5,d[R3+1]-5
——————————————————————
举个栗子:
0 0 0 0 0 0 ------ 0 1 0 0 -1 0 (对区间[1,3]+1)
0 0 0 0 0 0 ------ 0 1 1 1 0 0

#include<iostream>

using namespace std;

int d[6];
/*  0 1 2 3 4
1 3 7 5 2
2 4 8 5 2
2 1 5 2 2
2 1 10 7 7
*/
void add(int l,int r,int v)
{
d[l]+=v;
d[r+1]-=v;
} 

void func()
{	
int i;
int a[]={1,3,7,5,2};
add(0,2,1);		//0,2
add(1,3,-3);	//1,3
add(2,4,5);		//2,4
for(i=1;i<5;i++) d[i]+=d[i-1];
for(i=0;i<5;i++){
	a[i]+=d[i];
	cout<<a[i]<<" ";
}

}
int main()
{
func();
return 0;
}

二维差分
1 5 6 8
9 6 7 3
5 3 2 4
(0,0)到(2,1) +3 (1,1)到(2,2) -1
先进行差分标记
3 0 -3 0 0————3 3 0 0 0
0 -1 0 1 0————3 2 -1 0 0
0 0 0 0 0————3 2 -1 0 0
-3 1 3 -1 0————0 0 0 0 0
——————————————
1 5 6 8————4 8 6 8
9 6 7 3————12 8 6 3
5 3 2 4————8 5 1 4

 #include<iostream>

using namespace std;

const int n=3,m=4;
int a[n][m]={ {1,5,6,8},
		  {9,6,7,3},
		  {5,3,2,4} };
//(0,0)到(2,1) +3   (1,1)到(2,2) -1 
int d[n+1][m+1];
int sum[n+1][m+1];
void add(int x1,int y1,int x2,int y2,int v)
{
d[x1][y1]+=v;
d[x2+1][y1]-=v;
d[x1][y2+1]-=v;
d[x2+1][y2+1]+=v;
}
void func()
{	
int i,j;
add(0,0,2,1,3);
add(1,1,2,2,-1);

for(i=0;i<n+1;i++){
	for(j=0;j<m+1;j++){
		cout<<d[i][j]<<" ";
	}cout<<endl;
}cout<<endl;

//引入sum的原因是d[-1][-1]无法访问
sum[0][0]=d[0][0];				//第一个
for(i=1;i<m;i++)
sum[0][i]=sum[0][i-1]+d[0][i];	//第一行
for(j=1;j<n;j++)
sum[j][0]=sum[j-1][0]+d[j][0];	//第一列
 
for(i=1;i<n;i++){
	for(j=1;j<m;j++){
		sum[i][j]=d[i][j]+sum[i][j-1]+sum[i-1][j]-sum[i-1][j-1];
	}//上面这一循环其实是二维前缀和的变形
	 //d[i][j]+=d[i][j-1]+d[i-1][j]-d[i-1][j-1];
}

for(i=0;i<n;i++){
	for(j=0;j<m;j++){
		cout<<sum[i][j]<<" ";
	}cout<<endl;
}cout<<endl;

for(i=0;i<n;i++){
	for(j=0;j<m;j++){
		a[i][j]+=sum[i][j];
		cout<<a[i][j]<<" ";
	}
	cout<<endl;
}
}
int main()
{
func();
return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值