二维树状数组

二维的树状数组和一维的类似,分为单点更新区间查询和区间更新单点查询两种

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 }

 

posted @ 2018-04-23 23:18  _努力努力再努力x  阅读(241)  评论(0编辑  收藏  举报