Algorithm competition advanced guide ---0x42 (tree array) a simple integer problem 2

Topic

Insert picture description here

Input sample

5 10
1 2 3 4 5 6 7 8 9 10
Q 4 4
Q 1 10
Q 2 4
100 3 6 3
Q 2 4

Sample output

4
55
9
15

answer

  1. This question involves interval modification and interval query. Of course, it can be done with a line segment tree, but you can use a tree array to solve problems that can be solved with a tree array. You don’t need to use a line segment tree to solve it. If you don’t understand the tree array You can take a look here first , or use the idea of ​​a simple integer problem, a difference array (the tree array supports O(logn) single-point modification, interval query)
  1. "C lrd" means adding d to A[l], A[l+1],...,A[r], we can convert it into a difference array, for a range, we only need to modify the difference array The two endpoints b[l]+=c,b[r+1]-=c; so that the interval can be modified
  1. "Q lr" means the sum of the number l~r in the query sequence. After we convert the original array into a difference array, we cannot perform interval queries, because the prefix sum of the difference array is a value of the original array, not the interval sum of the original array, then how to find the interval sum of the original array?
    Insert picture description here

4. After the derivation of the above formula, we found that only two tree arrays need to be maintained, one is a[i]-a[i-1] and the other is i * (a[i]-a[i-1] ), In this way, the interval sum of [1,x] of the element group can be obtained, and then the arbitrary interval of the original array can be obtained by using the prefix and the idea, which is completely transformed into the basic operation of the tree array

Code

#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>


using namespace std;
typedef long long ll;
const int N = 1e5 + 10;

ll n, m;
ll a[N];  //原数组
ll tr1[N];  //b[i]的前缀和数组
ll tr2[N];   //i*b[i]的前缀和数组

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

void add(ll tr[], ll x, ll c) {
    
    
    for (ll i = x; i <= n; i += lowbit(i)) {
    
    
        tr[i] += c;
    }
}

ll sum(ll tr[], ll x) {
    
    
    ll res = 0;
    for (ll i = x; i; i -= lowbit(i)) {
    
    
        res += tr[i];
    }
    return res;
}

ll prefix_sum(ll x) {
    
    
    return sum(tr1, x) * (x + 1) - sum(tr2, x);
}

int main() {
    
    

    cin >> n >> m;
    for (int i = 1; i <= n; i++) scanf("%lld", &a[i]);
    for (int i = 1; i <= n; i++) add(tr1, i, a[i] - a[i - 1]);
    for (int i = 1; i <= n; i++) add(tr2, i, i * (a[i] - a[i - 1]));

    while (m--) {
    
    
        string op;
        int l, r, d;
        cin >> op >> l >> r;
        if (op == "Q") {
    
    
            cout << prefix_sum(r) - prefix_sum(l - 1) << endl;
        } else {
    
    
            cin >> d;
            add(tr1, l, d), add(tr1, r + 1, -d);
            add(tr2, l, l * d), add(tr2, r + 1, -(r + 1) * d);
        }
    }

    return 0;
}

Guess you like

Origin blog.csdn.net/qq_44791484/article/details/113826577