Color the ball

Time Limit: 9000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 6614    Accepted Submission(s): 3470

Problem Description
N
个气球排成一排,从左到右依次编号为1,2,3....N.每次给定2个整数a b(a <=
b),lele便为骑上他的“小飞鸽"牌电动车从气球a开始到气球b依次给每个气球涂一次颜色。但是N次以后lele已经忘记了第I个气球已经涂过几次颜
色了,你能帮他算出每个气球被涂过几次颜色吗?
 
Input
每个测试实例第一行为一个整数N,(N <= 100000).接下来的N行,每行包括2个整数a b(1 <= a <= b <= N)。
当N = 0,输入结束。
 
Output
每个测试实例输出一行,包括N个整数,第I个数代表第I个气球总共被涂色的次数。
 
Sample Input
3
1 1
2 2
3 3
3
1 1
1 2
1 3
0
 
Sample Output
1 1 1
3 2 1
 
Author
8600
思路:之前把这题A了,用线段树做的,现在学学树状数组,也不知道 Peter M. Fenwick 当时是怎么想到的,太神奇了,我花了一整天全在研究他的思路,到最后还是没什么进展,不知怎么想的,这就是大神吧。
 
它与线段树不同,线段树是平衡二叉树,对于一个区间很容易从直观上就可以将它划分,[a , b]的子区间(子树)为[a,(a+b)/2]和[(a+b)/2+1,b],很容易就看出来,而对于树状数组区间的划分则不是那样的,很难直接观察得到。那么到底什么是树状数组,下面讲讲我的理解,也算是花了一整天的总结吧,可能不全对。
 

设想我们有这样一个问题:给定一个序列,A1,A2,A3........An,现在需要频繁的查询区间(i,j)里面所有元素的和,而且这个序列中的元素是变化的。当然我们可以用最简单的暴力法,一个个加呗,这样时间复杂度为O(n),插入数据时间复杂度是O(1)的,更新是O(m),这样一来总的时间复杂度会是O(n×m),数据一旦变大,效率太低,此时就要用树状数组,也叫作二叉搜索树(Binary Indexed Trees)BIT。

它基于这样一个定义:令数组C[i] = A[i-2^k+1]+...+A[i],这样以来C[i]表示的就是区间(i-2^k+1,i)的和,这里k表示的是:i对应的二进制数末尾连续0的个数,比如8(10) = 1000(2),那么k = 3;它所维护的区间是不是很“晦涩”,不知道他是怎么想得,据说Peter M. Fenwick的这样定义的思路来源于二进制思想。我个人认为这是整个树状数组最有价值的部分,也是最值得研究的部分。

1,基于这样一个定义我们的问题来了,对于确定的i,如何计算k的值?换句话说我们要知道2^k的值,再换句话说就是计算二进制位中最右边那个1的位权,不然一切都不用谈了,没意义。而且要高效,其实可以利用C语言位运算来做(用的很巧妙):

我们可以这样表示一个二进制数:a1b,这里b都是0(0的个数可以是0),a任意,但必须保证1是最右边的那个1,例如 14(10) = 1100(2),那么a=1,b=00,

那么-a1b在计算机里是以补码表示的,即反码加1,我把它记为(a-)0(b-)+1,所以(b-)全为1了,所以(a-)0(b-)+1 = (a-)0(1...1)+1 = (a-)1(0...0), 它再与a1b按为与运算,a1b & (a-)1(0...0) = (0...0)1(0...0),这样就得到了2^k的值了,很神奇!

写个函数就是:

  1. int LowBit(int t)
  2. {
  3. return t & (-t);
  4. }

我们就把第一个问题解决了!

这个函数的功能就是寻找当前节点的父节点或者子节点!!!

2,那么我们如何来计算C[i]的值?就是说我们插入数据A[j]的时候如何来更新C[i]?我们不光要更新C[i],而且还要更新与A[j]有关的其他的C[k1]...C[kn],这样才能保证C[i]维护的值是正确的。

先来个图吧,这样看得明白。

例如我们修改A4的值那么C[4],C[8]...,直到n,都得更新,想想为什么?因为A4被C[4],C[8]...,覆盖!记住一点:某个数被修改,与他相关的区间都得受到牵连,这就是为什么暴力法慢的原因,而树状数组使得受到牵连的区间(即相关的父节点)不会多于LogN(我认为这得归功于那个牛逼的定义),想想为什么!更新函数可以这么写:
  1. void update(int pos,int val)
  2. {
  3. while(pos <= n)
  4. {
  5. c[pos] += val;
  6. pos += LowBit(pos);
  7. }
  8. return ;
  9. }

3,如何得到某个区间(i,j)的和呢?

我们高中就学过sum(i) = A1+A2+A3+...+Ai;

       sum(j) = A1+A2+A3+...+Aj;

那么sum(i->j)= sum(j)-sum(i);

现在问题又来了,怎么知道sum(n)的值的?

我们把1。。。n所包含的子区间的和加一起就可以了,现在关键是如何找区间了,比如给你13,让你求sum(13),怎么找13的子区间?这还得根据LowBit()函数的计算过程来逆退,刚才不是update函数是加得到的父区间,现在逆过来就减!函数如下:

  1. void Get_Result(int pos)
  2. {
  3. while(pos > )
  4. {
  5. sum += c[pos];
  6. pos -= LowBit(pos);
  7. }
  8. return ;
  9. }

三个函数都很简洁,代码比较简单,但思想绝不简单!特别是那个定义!

对于数状数组我今天就理解这么多,以得还的进一步理解。

AC代码:

  1. #include<stdio.h>
  2. #include<string.h>
  3. #define MAX 100005
  4. int c[MAX];
  5. int sum,n;
  6. int LowBit(int t)
  7. {
  8. return t & (-t);
  9. }
  10.  
  11. void update(int pos,int val)
  12. {
  13. while(pos <= n)
  14. {
  15. c[pos] += val;
  16. pos += LowBit(pos);
  17. }
  18. return ;
  19. }
  20.  
  21. void Get_Result(int pos)
  22. {
  23. while(pos > )
  24. {
  25. sum += c[pos];
  26. pos -= LowBit(pos);
  27. }
  28. return ;
  29. }
  30.  
  31. int main()
  32. {
  33. int a,b,i;
  34. while(~scanf("%d",&n) && n)
  35. {
  36. memset(c,,sizeof(c));
  37. for(i = ;i <= n;i ++)
  38. {
  39. scanf("%d%d",&a,&b);
  40. update(a,);
  41. update(b+,-);
  42. }
  43. for(i = ;i < n;i ++)
  44. {
  45. sum = ;
  46. Get_Result(i);
  47. printf("%d ",sum);
  48. }
  49. sum = ;
  50. Get_Result(i);
  51. printf("%d\n",sum);
  52. }
  53. return ;
  54. }

Color the ball----HDOJ1556的更多相关文章

  1. Color the ball HDOJ--1556

    Color the ball Time Limit: 9000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)To ...

  2. HDU 1556 Color the ball(线段树区间更新)

    Color the ball 我真的该认真的复习一下以前没懂的知识了,今天看了一下线段树,以前只会用模板,现在看懂了之后,发现还有这么多巧妙的地方,好厉害啊 所以就应该尽量搞懂 弄明白每个知识点 [题 ...

  3. hdu 1556:Color the ball(第二类树状数组 —— 区间更新,点求和)

    Color the ball Time Limit: 9000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)To ...

  4. hdu 1556:Color the ball(线段树,区间更新,经典题)

    Color the ball Time Limit: 9000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)To ...

  5. Color the Ball[HDU1199]

    Color the Ball Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)To ...

  6. 线段树--Color the ball(多次染色问题)

    K - Color the ball Time Limit:3000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u ...

  7. hdu 1199 Color the Ball

    http://acm.hdu.edu.cn/showproblem.php?pid=1199 Color the Ball Time Limit: 2000/1000 MS (Java/Others) ...

  8. hdoj 1556 Color the ball【线段树区间更新】

    Color the ball Time Limit: 9000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)To ...

  9. hdu 1199 Color the Ball(离散化线段树)

    Color the Ball Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) T ...

  10. Color the ball(树状数组+线段树+二分)

    Color the ball Time Limit : 9000/3000ms (Java/Other)   Memory Limit : 32768/32768K (Java/Other) Tota ...

随机推荐

  1. JSON.parse 函数应用 (复制备忘)

    JSON.parse 函数 JSON.parse 函数 (JavaScript) 将 JavaScript 对象表示法 (JSON) 字符串转换为对象. 语法 JSON.parse(text [, r ...

  2. Linux Master/Baremetal Remote 配置下的裸机调试

    为了实现在ZC702开发板上的两颗Cortex-A9处理器上实现Linux Master/Baremetal Remote 配置,并对Remote端的裸机程序进行调试,需要注意的几点如下: 一.建立p ...

  3. ubuntu下编译安装apache

    官网http://httpd.apache.org/download.cgi下载apache源码包后 /*解包*/ gzip -d httpd-2_x_NN.tar.gz tar -xf httpd- ...

  4. fstat().stat()函数

    int stat(const char *path, struct stat *buf); int fstat(int fd, struct stat *buf); 唯一不同是参数不同,其他一样. 文 ...

  5. iOS面试题6.30总结

    越来越多的人投入iOS这个行业中,但是作为刚才学校毕业的学生,我们没有任何经验.或者经验很少.但是这也不能阻挡我们对苹果的热情,想投入iOS的开发中.而作为进入企业的第一步,我们要参加面试.面试中我们 ...

  6. Windows7 下安装 CentOS6.5

    内容来自:http://blog.163.com/for_log/blog/static/2162830282013031031278/第一部分:安装前准备1. 准备两个fat32格式的分区,一个用于 ...

  7. 计划任务实现定时备份mysql数据库

    1.linux平台 30 3 * * * sh /data/tools/mysqlbackup.sh  每天3点半备份数据库mysqlbackup.sh(备份最近5天的数据): #设置数据库名,数据库 ...

  8. JBPM4中常用概念总结

    1. 流程定义(Process Definition)    流程定义是记录在xml文件中的对流程的描述,它包含唯一的流程开始节点和多个流程功能节点,每个节点之间使用transition进行连接. P ...

  9. 腾讯面试题 腾讯面试题:给40亿个不重复的unsigned int的整数,没排过序的,然后再给一个数,如何快速判断这个数是否在那40亿个数当中?

    腾讯面试题:给40亿个不重复的unsigned int的整数,没排过序的,然后再给一个数,如何快速判断这个数是否在那40亿个数当中?  这个题目已经有一段时间了,但是腾讯现在还在用来面试.腾讯第一次面 ...

  10. 5个有用的.net profiling工具(转)

    我们有时需要对研发的软件程序进行性能测试,这时需要用到一些Profilers工具.下面列出5个有用的.net Profilers: 1. JetBrains dotTrace JetBrains do ...