【二维树状数组】知识点讲解+例题x1

概念

概念的话感觉就不是很好理解,但是满足树状数组的功能特性:对数组进行简化(因为C数组的辅助),使得之后优化遍历的时间复杂度到log。因此,二维树状数组其实也就这个用,只是之前是针对一维,现在是针对二维。

百度百科这样写的,其实看不看懂问题不大:



模板

主要是要记住下面的方法!

单点更新 和 区间查询

其实A数组要不要都无所谓,因为C数组的更新其实就代表了A数组的更新。看题意。


区间查询操作一般是为了用于“子矩阵查询”,公式如上。

其实很好理解,区间查询sum(i,j)指的是从矩阵左上方拉到A[i][j]处的矩形,而把它修剪一下,就能得到想要的子矩阵。

画了个图理解:


黑色是整个矩阵,红色是想求的子矩阵,灰色是减去的矩阵,棕色是重新加上的矩阵(因为被多剪了一次)。

(这张图结合上面的公式理解即可)


例题



思路

直接套模板即可。

细节注意:因为用scanf比用cin快,而且要查询那么多次,所以我用的scanf,然后发现了一个知识点:如果出现多个scanf连用,一般是没问题的,但是如果,在用完一个scanf之后,接下来是一个需要输入“%c”的scanf,就要特别注意了!为什么?因为scanf的输入会在缓冲区留下一个空白字符(你敲的空格或回车),而如果下一个scanf是吃“%c”的话,吃掉的就会是这个空白字符,整个程序就乱了呀!所以,需要在吃"%c"的scanf之前加一个 getchar() 吃掉先前的空白字符

(在连用scanf 或 循环体中 ,如果有吃“%c”的scanf时,一定要注意!!!否则很难找到这个问题源)


代码

#include<iostream>
#include<bits/stdc++.h>
using namespace std;
const int maxn=1010;
int c[maxn][maxn];
int n;
void add(int i,int j,int v)
{
	for(int x=i;x<=n;x+=x&(-x))
	{
		for(int y=j;y<=n;y+=y&(-y))
			c[x][y]+=v;
	}
}
int sum(int i,int j)
{
	int res=0;
	for(int x=i;x>0;x-=x&(-x))
	{
		for(int y=j;y>0;y-=y&(-y))
			res+=c[x][y];
	}
	return res;
}

int main()
{
	cin>>n;
	int q;
	scanf("%d",&q);
	char C;
	while(q--)
	{
		getchar();   //吃掉空白字符!!! 
		scanf("%c",&C);
		if(C=='C')
		{
			int a,b,c;
			scanf("%d%d%d",&a,&b,&c);
			add(a,b,c); 
		}
		else
		{
			int x1,y1,x2,y2;
			scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
			printf("%d\n",sum(x2,y2)-sum(x2,y1-1)-sum(x1-1,y2)+sum(x1-1,y1-1));
		}
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/m0_38033475/article/details/80342758