树状数组解决区间问题:单点、区间修改,单点、区间查询

前言

最近在复习算法的时候,刷到了一些针对于区间问题,所以在此记录。

注:此文章默认会使用树状数组,不会的可以参考这一篇文章:树状数组详解

一. 单点修改,单点查询

这个很简单,我们直接使用单纯的数组就可以了。

二. 单点修改,区间查询

#include <iostream>
using namespace std;

const int N = 1e5 + 10;
int tree[N], a[N];
int n, m;

int lowbit(int i){
    
    
    return i & (-i);
}

void modify(int i, int k){
    
    
    int x = i;
    while(i <= n){
    
    
        tree[i] += k;
        i += lowbit(i);
    }
}

int query(int i){
    
    
    int x = i, res = 0;
    while(i){
    
    
        res += tree[i];
        i -= lowbit(i);
    }
    return res;
}

int main(){
    
    
    cin >> n >> m;
    for(int i = 1; i <= n; i++){
    
    
        cin >> a[i];
        modify(i, a[i]);
    }
    while(m--){
    
    
        char op;
        cin >> op;
        if(op == 'Q'){
    
    
            int l, r;
            cin >> l >> r;
            cout << query(r) - query(l - 1) << '\n';
        }else{
    
    
            int i, k;
            cin >> i >> k;
            modify(i, k);
        }
    }
    return 0;
}

三. 区间修改,单点查询

我们这里考虑用树状数组+差分。

#include <iostream>
using namespace std;

const int N = 1e5 + 10;
int tree[N], a[N];
int n, m;

int lowbit(int i){
    
    
    return i & (-i);
}

void modify(int i, int k){
    
    
    int x = i;
    while(i <= n){
    
    
        tree[i] += k;
        i += lowbit(i);
    }
}

int query(int i){
    
    
    int x = i, res = 0;
    while(i){
    
    
        res += tree[i];
        i -= lowbit(i);
    }
    return res;
}

int main(){
    
    
    cin >> n >> m;
    for(int i = 1; i <= n; i++){
    
    
        cin >> a[i];
        modify(i, a[i] - a[i - 1]);
    }
    while(m--){
    
    
        char op;
        cin >> op;
        if(op == 'Q'){
    
    
            int i;
            cin >> i;
            cout << query(i) << '\n';
        }else{
    
    
            int l, r, k;
            cin >> l >> r >> k;
            modify(l, k);
            modify(r + 1, -k);
        }
    }
    return 0;
}

四. 区间修改,区间查询

这个稍微难点,详解可以看我在前言发的那篇文章。

#include <iostream>
using namespace std;

typedef long long ll;
const int N = 1e5 + 10;
ll tree1[N], tree2[N], a[N];
ll n, m;

ll lowbit(ll i){
    
    
    return i & (-i);
}

void modify(ll i, ll k){
    
    
    ll x = i;
    while(i <= n){
    
    
        tree1[i] += k;
        tree2[i] += (x - 1) * k;
        i += lowbit(i);
    }
}

ll query(ll i){
    
    
    ll x = i, res = 0;
    while(i){
    
    
        res += x * tree1[i] - tree2[i];
        i -= lowbit(i);
    }
    return res;
}

int main(){
    
    
    cin >> n >> m;
    for(int i = 1; i <= n; i++){
    
    
        cin >> a[i];
        modify(i, a[i] - a[i - 1]);
    }
    while(m--){
    
    
        char op;
        cin >> op;
        if(op == 'Q'){
    
    
            int l, r;
            cin >> l >> r;
            cout << query(r) - query(l - 1) << '\n';
        }else{
    
    
            int l, r, k;
            cin >> l >> r >> k;
            modify(l, k);
            modify(r + 1, -k);
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_52855744/article/details/123746905