• Range Sum Query


    操作: 

    单点更新,区间求和

    区间求和:如sum [3,10) 需要对19,5,12,26节点求和即可。

    观察可知,左端点为右子节点(奇数)时直接相加,右端点为左子节点(偶数)时直接相加,两边向中间移动并求其父节点。

     1 class NumArray {
     2 public:
     3     NumArray(vector<int> nums) {
     4         n = nums.size();
     5         tree.resize(n * 2); // 满二叉树
     6         buildTree(nums);
     7     }
     8 
     9     void buildTree(vector<int>& nums) {
    10         for (int i = n; i < n * 2; ++i) {
    11             tree[i] = nums[i - n];
    12         }
    13         for (int i = n - 1; i > 0; --i) {
    14             tree[i] = tree[i<<1] + tree[i<<1|1];
    15         }
    16     }
    17 
    18     void update(int i, int val) {
    19         tree[i += n] = val;
    20         while (i > 0) {
    21             tree[i / 2] = tree[i] + tree[i^1];
    22             i /= 2;
    23         }
    24     }
    25 
    26     int sumRange(int i, int j) { 
    27         int sum = 0;
    28         for (i += n, j += n; i <= j; i /= 2, j /= 2) {
    29             if ((i & 1) == 1) sum += tree[i++];
    30             if ((j & 1) == 0) sum += tree[j--];
    31         }
    32         return sum;
    33     }    
    34 
    35 private:
    36     int n;
    37     vector<int> tree;
    38 };

    Refer:

    Codeforces blog

    树状数组解法

    所有的奇数位置的数字和原数组对应位置的相同,偶数位置是原数组若干位置之和,若干是根据坐标的最低位 Low Bit 来决定的 ( x&-x )

    [i, j] 区间和:sum[j]-sum[i-1]

     1 class NumArray {
     2 public:
     3     NumArray(vector<int>& nums) {
     4         data.resize(nums.size());
     5         bit.resize(nums.size()+1);
     6         for(int i=0;i<nums.size();i++){
     7             update(i,nums[i]);
     8         }
     9     }
    10     
    11     void update(int i, int val) {
    12         int diff = val - data[i];
    13         for(int j=i+1;j<bit.size();j+=(j&-j)){
    14             bit[j]+=diff;
    15         }
    16         data[i] = val;
    17     }
    18     
    19     int sumRange(int i, int j) {
    20         return getSum(j+1)-getSum(i);
    21     }
    22     
    23     int getSum(int i){
    24         int res = 0;
    25         for(int j=i;j>=1;j-=(j&-j)){
    26             res+=bit[j];
    27         }
    28         return res;
    29     }
    30 private:
    31     vector<int> data;
    32     vector<int> bit; // 前面补0, 从1开始
    33 };
  • 相关阅读:
    g_pLog
    win-socket
    时间转字符串 各种格式
    linux自启动脚本.sh
    openssl之aes对称加密
    openssl生成密钥/证书
    win10下安装openssl
    GUI的最终选择 Tkinter(二):Label和Button组件
    GUI的最终选择 Tkinter(一):Tkinter最初体验
    练习十三:水仙花数,用for循环实现
  • 原文地址:https://www.cnblogs.com/demian/p/11253670.html
Copyright © 2020-2023  润新知