二维树状数组的差分,区间修改(学习总结)附poj2155练习

一维和二维树状数组最一般的就是单点修改和区间查询了。如果要完成区间修改这得借助差分.普通的差分a[i]=a[i]-a[i-1];如果放入二维数组中该怎么进行差分呢。
二维数组前缀和:
例如sum[x][y]表示的就是点(1,1)与点(x,y)之间的子矩阵内的元素和。
看一个矩阵:
无问

此时如果要求绿色区域矩阵的和(包含a(x1,y1)这个点)那么整个大矩阵减去橙白黑三个小矩阵,整个过程中橙色会被多减一次所以要加上来。ans=sum[x2][y2]-sum[x2][y1-1]-sum[x1-1][y2]+sum[x1-1][y1-1];(此时sum数组代表前缀和,a为原数组)
对比一下一维的前缀和与差分
一维差分:c[i]=c[i]-c[i-1];
一维前缀和:c[i]=c[i]+c[i-1];
令d[i][j]为二维数组的差分数组d[i][j]=a[i][j]-(a[i−1][j]+a[i][j−1]−a[i−1][j−1] );
当对一个字矩阵加上v时怎么处理呢。例如最中间的3*3矩阵
0 0 0 0 0
0 +v 0 0 -v
0 0 0 0 0
0 0 0 0 0
0 -v 0 0 +v
记录下四个位置就可以了
入门题poj2155

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define lowbit(x) ((x)&(-x))
#define INF 0x3f3f3f3f
const int N=1e3+100;
typedef long long ll;
using namespace std;
int tree[N][N],n;
void update(int x,int y,int val)
{
	for(int i=x;i<=n;i+=lowbit(i))
	{
		for(int j=y;j<=n;j+=lowbit(j))
		{
			tree[i][j]+=val;
		}
	}
}
int query(int x,int y)//query查的就是(1,1)到(x,y)的矩阵
{
	int sum=0;
	for(int i=x;i>0;i-=lowbit(i))
	{
		for(int j=y;j>0;j-=lowbit(j))
		{
			sum+=tree[i][j];
		}
	}
	return sum;
}
int main()
{
	int t;
	scanf("%d",&t);
	while(t--)
	{
		memset(tree,0,sizeof(tree));
		int q;
		scanf("%d%d",&n,&q);
		while(q--)
		{
			
			char s[2];
			scanf("%s",s);
			if(s[0]=='C')
			{
				int x1,y1,x2,y2;
				scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
				update(x1,y1,1);
				update(x1,y2+1,-1);
				update(x2+1,y1,-1);
				update(x2+1,y2+1,1);	
			}
			if(s[0]=='Q')
			{
				int x,y;
				scanf("%d%d",&x,&y);
				int  ans=query(x,y);//N*N矩阵最开始就是0,所以把tree数组作为差分数组
				printf("%d\n",ans%2);
			}
		}
		printf("\n");
	}
	return 0;
}

无论在一维还是二维中树状数组承担就是快速求和(可以理解为前缀和吧,更新的作用也是方便之后的快速查询)
个人对二维差分的一些理解,如果有什么错误还请帮忙指正,非常感谢!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值