알고리즘 경쟁 고급 가이드 --- 0x42 (트리 배열) 간단한 정수 문제 2

이야기

여기에 사진 설명 삽입

입력 샘플

5 1012
34 5678 9 10
Q44
Q 1 10
Q2
4100 3 6 3
Q2 4

샘플 출력

4
55
9
15

대답

  1. 이 질문에는 간격 수정 및 간격 쿼리가 포함됩니다. 물론 라인 세그먼트 트리를 사용하여 수행 할 수 있지만 트리 어레이를 사용하여 트리 어레이로 해결할 수있는 문제를 해결할 수 있습니다. 라인을 사용할 필요가 없습니다. 트리 배열을 이해하지 못한다면 먼저 여기를 살펴 보거나 간단한 정수 문제, 차분 배열 (트리 배열은 O (logn) 단일 포인트를 지원함)이라는 아이디어를 사용할 수 있습니다. 수정, 간격 쿼리)
  1. "C lrd"는 A [l], A [l + 1], ..., A [r]에 d를 추가하는 것을 의미합니다. 차이 배열로 변환 할 수 있습니다. 범위에 대해서는 차이 배열 만 수정하면됩니다. 간격을 수정할 수 있도록 두 끝점 b [l] + = c, b [r + 1]-= c;
  1. "Q lr"은 쿼리 시퀀스에서 숫자 l ~ r의 합계를 의미합니다. 원래 배열을 차이 배열로 변환 한 후에는 차이 배열의 접두사 합이 원래 배열의 간격 합이 아니라 원래 배열의 값이기 때문에 간격 쿼리를 수행 할 수 없습니다. 원래 배열?
    여기에 사진 설명 삽입

4. 위 공식을 도출 한 후 두 개의 트리 배열 만 유지하면된다는 것을 발견했습니다. 하나는 a [i] -a [i-1]이고 다른 하나는 i * (a [i] -a [i -1]), 이와 같이 요소 군 [1, x]의 구간 합을 구할 수 있으며, 완전히 변형 된 접두사와 아이디어를 이용하여 원래 배열의 임의 구간을 구할 수있다. 트리 배열의 기본 작업으로

암호

#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;
}

추천

출처blog.csdn.net/qq_44791484/article/details/113826577