Vijos
/ Vijos / 题库 /
SuperBrother打鼹鼠
这是一道二维树状数组的裸题目
#include <bits/stdc++.h>
using namespace std;
int n,m;
int c[1026][1026];
int lowbit(int x)
{
return x&(-x);
}
void update(int x,int y,int z)//将(x,y)的值+z
{
for(int i=x;i<=n;i+=lowbit(i))
for(int j=y;j<=n;j+=lowbit(j))
c[i][j]+=z;
}
int sum(int x,int y)
{
int s=0;
for(int i=x;i>0;i-=lowbit(i))
for(int j=y;j>0;j-=lowbit(j))
s+=c[i][j];
return s;
}
int main()
{
cin>>n;
while(1)
{
cin>>m;
if(m==3) break;
else if(m==1)
{
int x,y,z;
cin>>x>>y>>z;
update(x+1,y+1,z);
}
else if(m==2)
{
int x1,y1,x2,y2;
cin>>x1>>y1>>x2>>y2;
cout<<sum(x2+1,y2+1)-sum(x1,y2+1)-sum(x2+1,y1)+sum(x1,y1)<<endl;
}
}
return 0;
}
重点解释一下最后的这个公式:
cout<<sum(x2+1,y2+1)-sum(x1,y2+1)-sum(x2+1,y1)+sum(x1,y1)<<endl;
如图,那个红色方框就是我们最后要求的。(我们这里为了和计算机里二维数组的保持一致,我们把x坐标视为纵坐标)
红色方框:
(
x
2
,
y
2
)
(x2,y2)
(x2,y2)
绿色方框:
(
x
1
,
y
1
)
(x1,y1)
(x1,y1)
黄色方框:
(
x
2
,
y
1
−
1
)
(x2,y1-1)
(x2,y1−1) 边框上也是算的,不能一下全减去
蓝色方框:
(
x
1
−
1
,
y
2
)
(x1-1,y2)
(x1−1,y2)
因为多减去了一个阴影部分所以再加回来
(
x
1
,
y
1
)
(x1,y1)
(x1,y1)
所以最后就是:
s
u
m
(
x
2
,
y
2
)
−
s
u
m
(
x
1
−
1
,
y
2
)
−
s
u
m
(
x
2
,
y
1
−
1
)
+
s
u
m
(
x
1
,
y
1
)
sum(x2,y2)-sum(x1-1,y2)-sum(x2,y1-1)+sum(x1,y1)
sum(x2,y2)−sum(x1−1,y2)−sum(x2,y1−1)+sum(x1,y1)
由于树状数组下标不能为0,我们对每个点预处理时就已经都加了1,所以每个坐标都应相应+1.
所以最后变成了这个样子:
cout<<sum(x2+1,y2+1)-sum(x1,y2+1)-sum(x2+1,y1)+sum(x1,y1)<<endl;