树状数组 二维

我们来搞一个二维树状数组

首先初始数组还是a数组,二维的

搞一个b数组,也是二维,b[i][ ]就是a数组第i行的一维树状数组

b[2][1]=a[2][1];

b[2][2]=a[2][1]+a[2][2];

b[2][3]=a[2][3];

.......

最后我们来搞一个c数组,当然它还是二维的hhh

c[1][ ]就是第一行的树状数组,c[2][ ]是第一行加第二行,c[3][ ]是第三行,c[4][ ]就是前四行之和......

c[i][j]=i管理的树状数组中j项的和

看懂了么?其实就是在b数组的基础上,给b数组建了一个树状数组

a数组(初始数组)

2134
1543
5254

b数组(a数组的树状数组)

23310
16413
57516

 

c数组(b数组的树状数组)

23310
39723
57516

模拟一下单点修改

假如给a[1][2]+2;

a数组(初始数组)

2334
1543
5254

b数组(a数组的树状数组)

25312
16413
57516

 

c数组(b数组的树状数组)

25312
311725
57516

这就是二维树状数

组的修改过程,我们发现,c数组只有c[1][2],c[1][4],c[2][2],c[2][4]改变了,其实就是……怎么说呢,就是c数组的横坐标和纵坐标分别作为一个树状数组来看……(越绕越乱,自行理解)

如果没看懂,那就直接上代码吧

(其实我现在稍微有点懵,写完代码应该就懂了)

​#include<iostream>
using namespace std;
int a[10100][10100],b[10100][10100],c[10100][10100],n,m,k;
int lowbit(int x)
{
	return x&-x;
}
void modifyb(int x,int y,int z)
{
	for (int s=y;s<=m;s+=lowbit(s))
		b[x][s]+=z;
}
void modifyc(int x,int y,int z)
{
	for (int s=y;s<=n;s+=lowbit(s))
		c[s][x]+=z;
}
void modify(int x,int y,int z)
{
	for (int s=x;s<=n;s+=lowbit(s))
		for (int o=y;o<=m;o+=lowbit(o))
			c[s][o]+=z;
}
int query(int x,int y)
{
	int ans=0;
	for (int s=x;s>0;s-=lowbit(s))
		for (int o=y;o>0;o-=lowbit(o))
			ans+=c[s][o];
	return ans;
}
int main()
{
	scanf("%d%d%d",&n,&m,&k);
	for (int i=1;i<=n;i++) 
		for (int j=1;j<=m;j++)
			scanf("%d",&a[i][j]);
	for (int i=1;i<=n;i++)
		for (int j=1;j<=m;j++)
			modifyb(i,j,a[i][j]);
	for (int i=1;i<=m;i++)
		for (int j=1;j<=n;j++)
			modifyc(i,j,b[j][i]);
	for (int i=1;i<=k;i++)
	{
		int p;
		scanf("%d",&p);
		if (p==1)
		{
			int Q,w,q;
			scanf("%d%d%d",&Q,&w,&q);
			modify(Q,w,q);
		}
		if (p==2)
		{
			int w,q,W,Q,anss;
			scanf("%d%d%d%d",&w,&q,&W,&Q);
			anss=query(W,Q)+query(w-1,q-1)-query(W,q-1)-query(w-1,Q);
			printf("%d\n",anss);
		}

	}
	return 0;		
}
​

那么树状数组就彻底告一段落了 

至此,已经解决了:树状数组单点修改区间查询,树状数组区间修改单点查询,树状数组区间修改区间查询,二维树状数组

树状数组大法好!!!

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值