今天学习了一维的数组数组,就又学了学二维的树状数组,
其实,二维树状数组和一维的套路差不多,就是在处理的时候有一点点不同而已。。
一维树状数组更新是这样的:
void add(int x,int val)
{
for(;x<=n;x+=lowbit(x))
{
num[x]+=val;
}
}
二维树状数组更新是这样的:
void add(int x,int y,int val)
{
for(int i=x;i<=n;i+=lowbit(i)) //n就是二维数组的长度
{
for(int j=y;j<=n;j+=lowbit(j))
{
num[i][j]+=val;
}
}
}
一维树状数组查询是这样的:
int query(int x)
{
int ans=0;
for(;x>0;x-=lowbit(x))
{
ans+=c[i];
}
return ans;
}
查询的是1到x的数总和。
二维树状数组查询是这样的
int query(int x,int y)
{
int ans=0;
for(int i=x;i>0;i-=lowbit(i))
{
for(int j=y;j>0;j-=lowbit(j))
{
ans+=num[i][j];
}
}
return ans;
}
查询的是(1,1)到(x,y)的数的总和。(比如二维数组a【10】【10】,(1,1)到(3,3)=(1,1)+(1,2)+(1,3)+(2,1)+(2,2)+(2,3)+(3,1)+(3,2)+(3,3),即(1,1)是矩形的左上角,(3,3)矩形的右下角,围成的矩形的和)
例题:poj-1195
题意:
给出一个全0的矩阵,然后一些操作
0 S:初始化矩阵,维数是S*S,值全为0,这个操作只有最开始出现一次
1 X Y A:对于矩阵的X,Y坐标增加A
2 L B R T:询问(L,B)到(R,T)区间内值的总和
3:结束对这个矩阵的操作
思路:
使用二维树状数组进行操作
代码:
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <vector>
#include <set>
#include <map>
#include <string>
#include <cstring>
using namespace std;
int a[1030][1030],c[1030][1030];
int n;
void read(int x,int y,int num)
{
for(int i=x;i<=n;i+=i&-i)
{
for(int j=y;j<=n;j+=j&-j)
{
c[i][j]+=num;
}
}
}
int sum(int x,int y)
{
int ans=0;
for(int i=x;i>0;i-=i&-i)
{
for(int j=y;j>0;j-=j&-j)
{
ans+=c[i][j];
}
}
return ans;
}
int main()
{
int m;
memset(c,0,sizeof(c));
while(scanf("%d",&m))
{
if(m==0)
{
//int n;
//cin>>n;
scanf("%d",&n);
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
a[i][j]=0;
}
else if(m==1)
{
int x,y,s;
scanf("%d%d%d",&x,&y,&s);
x++;
y++;
//s++;
read(x,y,s);
}
else if(m==2)
{
int x1,y1,x2,y2;
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
x1++;y1++;x2++;y2++;
//cout<<sum(x2,y2)-sum(x1-1,y1-1)<<endl;
printf("%d\n",sum(x2,y2)-sum(x2,y1-1)+sum(x1-1,y1-1)-sum(x1-1,y2));
}
else
{
break;
}
}
return 0;
}