• 树状数组


     一、插点问线,如“士兵杀敌(二)”要向上修改,向下统计;一般是修改某个位置上的值,查找的是一段区间的和;
    二、插线问点,如“士兵杀敌(四)”要向上统计,向下修改;一般是修改一段区间的值,查找的是某个位上的值;

    下图中的C数组就是树状数组,a数组是原数组

     
     
     
     
     
     
    可以发现这些规律
    C1=a1
    C2=a1+a2
    C3=a3
    C4=a1+a2+a3+a4
    C5=a5
    ……
    C8=a1+a2+a3+a4+a5+a6+a7+a8
    ……
    C2^n=a1+a2+….+a2^n
     
     
    对于序列a,一个(树状)数组C定义C[i] = a[i – 2^k + 1] + … + a[i],k为i在二进制下末尾0的个数。
    以上可以看出:设节点编号为i,那么这个节点管辖的区间为2^k
     
    算这个2^k有一个快捷的办法,
    定义一个函数如下即可:
    int lowbit(int x)
    {
    return x & (x ^ (x – 1));
    //等价于return x & (-x);
    }
     
    修改算法:例如(给某个结点i加上x):   
    step1: 当i > n时,算法结束,否则转第二步;  
    step2: Ci = Ci + x, i = i + lowbit(i)转第一步。  
     i = i +lowbit(i)这个过程实际上也只是一个把末尾1补为0的过程。   对于数组求和来说树状数组简直太快了! 
     具体函数如下:
    void update(int i , int x)
    {  
     while(i <= n)  
     {
      C[i] += x;
      i += Lowbit(i);  
     }   
    }
     
     
    若要求数组a的1~n项和,
    可以依据如下求和算法即可:
     step1: 令sum = 0,转第二步;
     
    step2: 假如n <= 0,算法结束,返回sum值,否则sum = sum + Cn,转第三步;
      
    step3: 令n = n – lowbit(n),转第二步。
      
    具体求和函数如下:
    int Sum(int n)
    { int sum = 0;   
            while (n> 0)  
     {   sum += C[n];  
                      n -= Lowbit(n);  
     }  
     return sum;  
    }
     
     
     
  • 相关阅读:
    [LeetCode]78. Remove Nth Node From end of List删除链表中倒数第N个节点
    [LeetCode]77. Reverse Linked List反转链表
    [LeetCode]76. Permutation Sequence全排列序列
    [LeetCode]75. Pow(x,n)幂运算
    粘连字符分割初探~~
    验证码识别学习~~
    用VS2010编C#程序扫盲 2
    用VS2010编C#程序扫盲
    验证码降噪方法汇总~~~~~
    新生活......
  • 原文地址:https://www.cnblogs.com/xiaofanke/p/3102505.html
Copyright © 2020-2023  润新知