树状数组

关于树状数组

cite

以 O(logn) 的时间复杂度查找、改变前缀和数组

要注意:
树状数组 c 里面存的不是对应点的值、也不是前缀和的值,是树状数组的值
但是可以利用树状数组对一个区间进行 log n 的时间复杂度的改变或求某点前缀和

//O(nlogn) 初始化
for(int i = 1;i <= n;i ++) add(i,a[i]);

楼兰图腾

#include<iostream>
#include<algorithm>
#include<cstring>

using namespace std;

typedef long long ll;

const int N = 200010;

int a[N],tr[N];
int n;
int g[N],l[N];
ll res1 = 0,res2 = 0;

int lowb(int x){
    return x & -x;
}

// pos 位置加x
void add(int pos,int x){
    for(int i = pos;i <= n;i += lowb(i)) tr[i] += x;
}

//求 1~pos
int sum(int pos){
    int res = 0;
    for(int i = pos;i;i -= lowb(i)) res += tr[i];
    return res;
}

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

    for(int i = 1;i <= n;i ++){
        int temp = a[i];

        g[i] = (sum(n) - sum(temp));
        l[i] = sum(temp - 1);

        add(temp,1);
    }

    memset(tr,0,sizeof tr);

    for(int i = n;i;i --){
        int temp = a[i];
        
        res1 += (ll)g[i] * (sum(n) - sum(temp));
        res2 += (ll)l[i] * sum(temp - 1);

        add(temp,1);
    }

    cout << res1 << ' ' << res2;
}

树状数组实现差分

#include<iostream>
#include<cstring>

using namespace std;

const int N = 100010;

typedef long long ll;

int n,m;
int a[N],tr[N];

int lowb(int x){
    return x & -x;
}

void add(int pos,int x){
    for(int i = pos;i <= n;i += lowb(i)) tr[i] += x;
}

ll sum(int pos){
    ll res = 0;
    for(int i = pos;i;i -= lowb(i)) res += tr[i];
    return res;
}

int main(){
    cin >> n >> m;

    for(int i = 1;i <= n;i ++) cin >> a[i];

    for(int i = 1;i <= n;i ++) add(i,a[i] - a[i - 1]);     //构造差分数组

    while(m --){
        string op;
        cin >> op;

        if(op == "Q"){
            int x;
            cin >> x;

            cout << sum(x) << endl;
        }else{
            int l,r,d;
            cin >> l >> r >> d;

            add(l,d),add(r + 1,-d); //差分计算
        }
    }
}

more complex

感觉没必要,可以写线段树

posted @ 2021-10-11 20:10  Xuuxxi  阅读(30)  评论(0)    收藏  举报