二维的树状数组和一维的类似,分为单点更新区间查询和区间更新单点查询两种
1、单点更新,区间查询
add(int x, int y, int d):tree[x][y] += d;
sum(int x, int y):返回(1,1)到(x, y)之和
注意:
修改某一点的值,num[x][y] += d;调用add(x, y, d);
计算顶点(x1, y1), (x2, y2)的区域内的数之和,调用
sum(x2, y2) – sum(x2, y1 - 1) – sum(x1 – 1, y2) + sum(x1 – 1, y1 - 1);(前缀和思想)
(x, y)要从(1, 1)开始,(0, 0)会导致无限循环超时
1 int lowbit(int x) 2 { 3 return x & (-x); 4 } 5 //修改tree[x][y] += d; 6 void add(int x, int y, int d) 7 { 8 for(int i = x; i <= n; i += lowbit(i)) 9 { 10 for(int j = y; j <= n; j += lowbit(j)) 11 { 12 tree[i][j] += d; 13 } 14 } 15 } 16 //从(1,1)到(x, y)数字之和 17 ll sum(int x, int y) 18 { 19 ll ans = 0; 20 for(int i = x; i > 0; i -= lowbit(i))//等于0会无限循环 21 { 22 for(int j = y; j > 0; j -= lowbit(j)) 23 { 24 ans += tree[i][j]; 25 } 26 } 27 return ans; 28 }
2、区间更新,单点查询
add(int x, int y, int d):(1,1)到(x,y)均加上d
sum(int x, int y):返回(x, y)点的值
注意:
1.区域[x1, y1]到[x2, y2]加上d:
调用:
add(x2, y2, d);
add(x1 - 1, y1 - 1, d);
add(x2, y1 - 1, -d);
add(x1 - 1, y2, -d);
2.查询某一点值 sum(x, y);
1 int lowbit(int x) 2 { 3 return x&(-x); 4 } 5 int sum(int x, int y) 6 { 7 int ret = 0; 8 for(int i = x; i <= n; i += lowbit(i)) 9 { 10 for(int j = y; j <= n; j += lowbit(j)) 11 ret += tree[i][j]; 12 } 13 return ret; 14 } 15 void add(int x, int y, int d) 16 { 17 for(int i = x; i > 0; i -= lowbit(i)) 18 { 19 for(int j = y; j > 0; j -= lowbit(j)) 20 tree[i][j] += d; 21 } 22 }