SPOJ - MATSUM Matrix Summation---二维树状数组
题目链接:
https://vjudge.net/problem/SPOJ-MATSUM
题目大意:
二维数组,两种操作
SET 将某点设置成x
SUM 求某个区域之和
解题思路:
这里用二维树状数组
SUM可以直接求出来
这里将某点设置成x,和树状数组不同,树状数组是讲某点加上一个值,但是可以另外建一个数组存储当前所有点的数值,如果要将(x, y)设置成d的话,可以先把该点减去a[x][y]再加上d
合并一下就是:add(x, y, d - a[x][y])
1 #include<iostream> 2 #include<string> 3 #include<cstdio> 4 #include<cstring> 5 using namespace std; 6 typedef long long ll; 7 const int maxn = 1025; 8 int tree[maxn][maxn]; 9 int a[maxn][maxn];//记录当前每个位置的值 10 int n; 11 int lowbit(int x) 12 { 13 return x & (-x); 14 } 15 //修改tree[x][y] += d; 16 void add(int x, int y, int d) 17 { 18 for(int i = x; i <= n; i += lowbit(i)) 19 { 20 for(int j = y; j <= n; j += lowbit(j)) 21 { 22 tree[i][j] += d; 23 } 24 } 25 } 26 //从(1,1)到(x, y)数字之和 27 ll sum(int x, int y) 28 { 29 ll ans = 0; 30 for(int i = x; i > 0; i -= lowbit(i))//等于0会无限循环 31 { 32 for(int j = y; j > 0; j -= lowbit(j)) 33 { 34 ans += tree[i][j]; 35 } 36 } 37 return ans; 38 } 39 40 int main() 41 { 42 int T; 43 scanf("%d", &T); 44 while(T--) 45 { 46 scanf("%d", &n); 47 memset(tree, 0, sizeof(tree)); 48 memset(a, 0,sizeof(a)); 49 char s[5]; 50 int x, y, z, x1, y1, x2, y2; 51 while(scanf("%s", s)) 52 { 53 if(s[0] == 'E')break; 54 if(s[1] == 'E')//SET 55 { 56 scanf("%d%d%d", &x, &y, &z); 57 x++; 58 y++;//必须从(1,1)开始 59 add(x, y, z - a[x][y]);//利用之前该位置的数值,就可以把该点设置成z 60 a[x][y] = z; 61 } 62 else if(s[1] == 'U')//SUM 63 { 64 scanf("%d%d%d%d", &x1, &y1, &x2, &y2); 65 x1++, y1++, x2++, y2++; 66 ll ans = 0; 67 ans += sum(x2, y2); 68 ans += sum(x1 - 1, y1 - 1); 69 ans -= sum(x1 - 1, y2); 70 ans -= sum(x2, y1 - 1); 71 printf("%lld\n", ans); 72 } 73 } 74 } 75 return 0; 76 }
越努力,越幸运