首页 > 代码库 > hdu 1541 树状数组

hdu 1541 树状数组

  1. #include <stdio.h>
  2. #include <string>
  3. #include <algorithm>
  4. #include <stdlib.h>
  5. using namespace std;
  6. #define MAX 32000
  7. int num[MAX+100];
  8. int lowbit(int x)
  9. {
  10. return x&(-x);
  11. }
  12. void modify(int x)
  13. {
  14. for(int i=x; i<32010; i+=lowbit(i))
  15. num[i]++;
  16. }
  17. int sum(int x)
  18. {
  19. int all =0;
  20. for(int i=x; i>0; i-=lowbit(i))
  21. all += num[i];
  22. return all;
  23. }
  24. int level[MAX+100];
  25. int main()
  26. {
  27. //freopen("read.txt", "r", stdin);
  28. int n;
  29. while(~scanf("%d", &n) )
  30. {
  31. memset(level, 0, sizeof(level));
  32. memset(num, 0, sizeof(num) ); //初始化问题重要
  33. int x, y;
  34. for(int i=0; i<n; i++)
  35. {
  36. scanf("%d%d", &x, &y);
  37. level[sum(x+1)]++;
  38. modify(x+1);
  39. }
  40. for(int i=0; i<n; i++)
  41. printf("%d\n", level[i]);
  42. }
  43. }
  44. /*
  45. 题目意思就是说,给你一张star maps,每个star有自己的level,level是这样计算的:(Let the level of a star be an amount of the stars that are not higher and not to the right of the given star.)统计这个star左下角star的个数,就是这个star的level。现在要你总计图中level从0到N-1的star分别有多少个?
  46. 题目输入描述中明确告诉我们,输入的坐标是按Y的升序、如果Y相等,则按X的升序。所以我们发现我们可以完全忽略Y,只要统计小于本身X的star个数,就是level了。现在我们用一个数组a[]统计X坐标为i的个数(增加一个既a[i]++;);同时对每个star计算的得level。
  47. 这样对于X坐标为j的star,他得level为:
  48. level=a[0]+a[1]+a[2]+…+a[j]
  49. 如果这样计算的话,每个level最坏时间要用O(m),计算n-1个level,这样要用O(mn)的时间复杂度,对于这题的数据而言,这无疑是无法接受的。我们发现,对于计算level,这是个查询区间问题sum[0,j], 如果没有元素的变更(既数组a是不变的),我们完全可以存储sum[0,k](k=0,2,……),然后对任意给定的查找区间[i,j],都可以方便的用ans=sum[1,j]-sum[1,i-1],当然这只是没有元素改变的情况下的比较优化的解法.那么对于有元素变更的问题是否有更高效的方法呢?这让我们想到的树状数组。
  50. 树状数组所针对问题:已知数组a[],元素个数为n,现在更改a中的元素,要求得新的a数组中i到j区间内的和(1<=i<=j<=n).
  51. 这题是比较简单和明显的树状数组,我们先不讨论如何实现树状数组。只告诉你树状数组现在有2个操作:
  52. (1) add(int i,int val) //将第i个元素更改val
  53. (2) sum(int i) //求前i项和
  54. 所以这题我们的伪代码可以如下实现:
  55. for(i=0;i<n;i++)
  56. {
  57. 1. sacnf(x,y);
  58. 2. cnt[sum(x+1)]++;
  59. 3. add(x+1,1);
  60. 4.
  61. }
  62. 5.print:cnt[0,n-1];
  63. 上面因为树状数组是从1开始计数的,而坐标有可能为0,所以我们统一都加1;sum(x+1)就是计算当前star的level值,所以当前level个数加1;add(x+1,1)操作表示对当前元素更改(既+1);最后打印cnt数组。
  64. 树状数组的实现及其思想
  65. 那么树状数组是如何实现快速对数组更新和区间求和的呢?
  66. 关于树状数组的实现和思想,这个再不细说,参考下面资料:
  67. http://baike.baidu.com/view/1420784.htm
  68. http://www.cnblogs.com/yykkciwei/archive/2009/05/08/1452889.html
  69. */



来自为知笔记(Wiz)


附件列表

     

    hdu 1541 树状数组