在一个初始矩阵map中进行操作 初始值为0
4种操作
输入0 后面跟着n为矩阵的size 为n*n
输入1 后面跟着 x y v 意思就是在 (x,y)位置的数增加 v
输入2 后面跟着 x1 y1 x2 y2 意思就是查询(x1 ,y1 )到(x2,y2)中的数的和
输入3 程序停止
update操作很简单 就是运用二维树状数组在(x,y)增加v就可以了 如果v<0也一样就是减
getsum求和操作也差不多 想一下在四边形(x1,y1 )到(x2,y2)中求和其实就是
(1,1)到(x2,y2)的总和 - (1,1)到(x1-1,y2)的总和 - (1,1)到(x2,y1-1)的总和再 + (1,1)到(x1,y1)的和
因为(x1,y1)在 (1,1)到(x1-1,y2)的总和 - (1,1)到(x2,y1-1)的总和 中被减了两次
自己画画图应该就可以理解了
至于坐标的++是因为如果坐标为0的话 low(0)会死循环 其实坐标全部++的话结果是一样的
写的时候吧memset函数放在了while里面.....然后自己很无语了查了一下
上代码:
#include<cstdio> #include<cstring> #include<algorithm> #include<iostream> using namespace std; const int N=1102; int map[N][N]; int n; int low(int i) { return i&(-i); } void update(int x,int y,int v) { //printf("n= %d",n); for(int i=x; i<=n; i+=low(i)) for(int j=y; j<=n; j+=low(j)) { // printf("x=%d y=%d v=%d\n",x,y,v); map[i][j]+=v; // printf("v= %d ",v); } } int getsum(int x,int y) { int sum=0; for(int i=x; i>0; i-=low(i)) for(int j=y; j>0; j-=low(j)) sum+=map[i][j]; return sum; } int main() { int m,x,y,x1,y1,x2,y2; int a; int num; scanf("%d%d",&m,&n); // printf("m== %d n== %d",m,n); memset(map,0,sizeof(map)); n++; //printf("n= %d",n); while(cin>>num&&num!=3) { if(num==1) { // printf("num==1\n"); scanf("%d%d%d",&x,&y,&a); x++; y++; //printf("x=%d y=%d a=%d\n",x,y,a); update(x,y,a); } if(num==2) { // printf("num==2\n"); scanf("%d%d%d%d",&x1,&y1,&x2,&y2); x1++; y1++; x2++; y2++; int ans=getsum(x2,y2)-getsum(x1-1,y2)-getsum(x2,y1-1)+getsum(x1-1,y1-1); printf("%d\n",ans); } } return 0; }