hdu--2642--二维BIT

BIT---Binary Index Tree. 树状数组...关于它的入门介绍 网上有很多博客 我这边不具体展开写了 就想提一些..

lowbit(x)是真正的这个树状数组的核心 都是靠它来传递的

网上 那张经典的图 有必要好好模拟计算一下 一维是二维的基础。。

使用的好 它能解决很多线段树可以解决的问题..当然有些问题 它是不能解决的..

这题 应该算让我们认识下 二维树状数组的吧 关于它的资料 网上不是很多 小白书上 似乎只是一笔带过 我忘了...

二维树状数组一般是用来计算子矩阵的和 可以看成在一个二维坐标系上 有X轴 Y轴

代码 其实很简单 就是多增加一个for而已 但是需要好好地理解它 因为三维 甚至更高维度的也会出现..

我想 二维树状数组 最让自己难计算的就是子矩阵之和了  假如给你两点(x1,y1)  (x2,y2)让你求得它的矩阵每个格子相加总的和是多少?

我画张图 来有助理解---这就是接下去用代码来完成的

 

 

 

这里 假设 x2>=x1   y2>=y1 当然题目有时候会故意出数据是x1>x2  y2>y1的 我们就要将它们进行交换  这样的目的是为了计算出和的时候可以正确表示

在一维中 getSum(x)就是前X个元素的和 那么二维就是getSum(x,y)前X行前J列的元素的和.

因为x1,y1是要取到的 所以需要-1 那么 其实我的图 画的是有问题的...理解就好 艹了=-=

所以getSum(x2,y2)=S1+S2+S3+S4    getSum(x1-1,y1-1)=S3  getSum(x2,y1-1)=S4+S3 getSum(x1-1,y2)=S2+S3

let see code

这边 需要将它给你的坐标分别+1  是因为 题目的数据范围从0开始

但是 lowbit(0)=0 这样会造成死循环的=-=

 1 #include <iostream>
 2 #include <cstring>
 3 #include <algorithm>
 4 using namespace std;
 5 
 6 const int size = 1010;
 7 int tree[size+5][size+5];
 8 bool flag[size+5][size+5];
 9 
10 int lowbit( int x )
11 {
12     return x&-x;
13 }
14 
15 void update( int x , int y , int num )
16 {
17     for( int i = x ; i<=size ; i+=lowbit(i) )
18     {
19         for( int j = y ; j<=size ; j+=lowbit(j) )
20         {
21             tree[i][j] += num;
22             //cout << tree[i][j] << endl;
23         }
24     }
25 }
26 
27 int getSum( int x , int y )
28 {
29     int sum = 0;
30     for( int i = x ; i ; i-=lowbit(i) )
31     { 
32         for( int j = y ; j ; j-=lowbit(j))
33         {
34             sum += tree[i][j];
35         }
36     }
37     return sum;
38 }
39 
40 int main()
41 {
42     cin.sync_with_stdio(false);
43     char ch;
44     int m , x , y , x1 , y1 , x2 , y2 , ans;
45     cin >> m;
46     memset( tree , 0 , sizeof(tree) );
47     memset( flag , false , sizeof(flag) );
48     while(m--)
49     {
50         cin >> ch;
51         if( ch=='Q' )
52         {
53             cin >> x1 >> x2 >> y1 >> y2;
54             ++ x1;
55             ++ y1;
56             ++ x2;
57             ++ y2;
58             if(x1>x2)
59                 swap(x1,x2);
60             if(y1>y2)
61                 swap(y1,y2);
62             ans = getSum(x2,y2) + getSum(x1-1,y1-1) - getSum(x2,y1-1) - getSum(x1-1,y2);
63             cout << ans << endl;
64         }
65         else 
66         {
67             cin >> x >> y;
68             ++ x;
69             ++ y;
70             if( ch=='B' )
71             {
72                 if(!flag[x][y])
73                 {
74                     flag[x][y] = true;
75                     update( x , y , 1 );
76                 }
77             }
78             else
79             {
80                 if( flag[x][y] )
81                 {
82                     flag[x][y] = false;
83                     update( x , y , -1 );
84                 }
85             }
86         }
87     }
88     return 0;
89 }
View Code

 

today:

  你从不讲真心话

  叫我如何大冒险

  

  寂寞拥抱寂寞

  难道就不寂寞

 

转载于:https://www.cnblogs.com/radical/p/3933975.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值