Stay Hungry,Stay Foolish!

树状数组

概念

https://zhuanlan.zhihu.com/p/92920381

树状数组(Binary Indexed Tree, 又Fenwick Tree)其实并不是一棵树,只是对数组各元素进行逻辑上的划分。根据维基百科,树状数组是一种用于高效计算数列前缀和的数据结构,它可以以O(logn)的时间得到任意前缀和(两个前缀和相减即可得到区间和),并同时支持以O(logn)的时间对数组某个值进行修改,空间复杂度为O(n)。由此可见,我们可以用树状数组解此题,使sumRangeupdate的复杂度均为O(logn)。因此我们有必要来了解一下树状数组。

 

视频帮助理解

https://www.bilibili.com/video/BV1ce411u7qP/?spm_id_from=333.337.search-card.all.click&vd_source=41b9bfb5ef0a4175a4cb4170a475f680

 

参考理解文章

https://zhuanlan.zhihu.com/p/99167607

 

图文并茂

https://zhuanlan.zhihu.com/p/93795692

 

 

https://zhuanlan.zhihu.com/p/375123608

 

 

 

题目

https://www.luogu.com.cn/problem/P3374

 

Code

#include <bits/stdc++.h>
#include <unistd.h>
using namespace std;

int v[500005], bit[500005], data[500005];

int n, m;

int lowBit(int j){
    return j & (-j);
}

int sum(int i){ // 前idx个数的和, logn
    // 这里的i从1开始编号
    int res = 0;
    while(i > 0){
        res += bit[i];
        i -= lowBit(i);
    }
    return res;
}

int sumRange(int i, int j) { //logn
    return sum(j) - sum(i-1);
}

void update(int i, int val) { //logn
    int diff = val - data[i];
    data[i] = val;
    // bit中下标从1开始
    while(i <= n){
        bit[i] += diff;
        i += lowBit(i);
    }
}

void print(){
    for(int i=1; i<=n; i++){
        cout << bit[i] << ",";
    }

    cout << endl;
}

int main() {
    cin >> n >> m;
    
    for(int i=1; i<=n; i++){
        cin >> v[i];
    }

    for(int i=1; i<=n; i++){
        update(i, v[i]);
        
//        cout << "-------------" << endl;
//        cout << "update i=" << i << " with v[i]=" << v[i] << endl;
//        
//        print();
    }

    for(int i=0; i<m; i++){
        int action, x;
        cin >> action >> x;
        
        if (action == 1){
            // add k to x pos
            int k;
            cin >> k;
            
            update(x, k+data[x]);
            
//            cout <<"----- add k=" << k << " to x=" << x << endl;
//            print();
            
        } else if (action == 2){
            // query sum in the range of [x, y]
            int y;
            cin >> y;
            
            cout << sumRange(x, y) << endl;
        }
    }
}

 

posted @ 2023-07-11 22:33  lightsong  阅读(10)  评论(0编辑  收藏  举报
Life Is Short, We Need Ship To Travel