zoukankan      html  css  js  c++  java
  • 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 ", 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. */





    附件列表

    • 相关阅读:
      java内联函数
      jvm垃圾回收
      jvm内存管理
      java进程和线程的区别
      jvm
      简单易学的SSM(Spring+SpringMVC+MyBatis)整合
      Spring之声明式事务
      SpringMVC知识点小结
      Servlet之文件的上传与下载
      java使用字节流和字符流实现文件复制
    • 原文地址:https://www.cnblogs.com/sober-reflection/p/f9ca7bf4b860062d157757b8fcd835f8.html
    Copyright © 2011-2022 走看看