POJ- 3468 A Simple Problem with Integers Line segment tree interval modification + query | Tree array interval modification + query

The meaning of the question is that the classic two operations
Q se means query the sum in the interval from s to e
C se add means add s to e to both the element size in the add
interval 1e9
interval length and the number of queries 1e5

Analysis:
Although this question is a bare line segment tree interval modification + query + delay mark,
it is better to use a simple tree-like array to do the complicated code.
First of all, let's see that the tree-like array is a kind of data that is used to find the prefix and more convenient The structure
sum[i] = Sigma a[i] = Sum(bit[x])
and the interval modification is not difficult to implement. It
is introduce a difference array del
del[i] to represent the modification of i~n
. In this case, the most del[ i] Calculate the prefix sum to get all the modifications of i~n,
because the modification of each element before i is the modification of all the following elements,
so when we count the modifications of i~n, we need to put the previous modification items All are added up.
Here you can use the tree array to count the prefix sum

That is, when we modify the interval s~e, we use del[s]+add to indicate the modification of i~n,
but
do not modify it after e, so we will perform the operation of del[e+1]-add. When modifying a single-point query, it can be represented by the original a[i]+sum(del[i]) [accumulated sum of information from 1-i]

When we need to find the interval query s~e,
let first look at how to find the sum of 1~i
sigma(i) = a[1] + del[1]+ a[2]+ del[1] + del[2 ] +…+a[i]+del[1]+del[2]+…+del[i]
= a[1]+a[2]+…+a[i] + del[1] (i)+del[2] (i-1) +...+del[i] *1
= a[1]+a[2]+...+a[i] + del[1] (i-1 +1)+del[2] (i-2+1) +...+del[i] *(i-i+1)
= Sigma(a[xi]) + Sigma(del[xi ]*( i - xi +1 ) )
= Sigma(a[xi]) + Sigma(del[xi])* ( i +1 ) ) -Sigma(del[xi] * xi )

It can be seen that the first Sigma is static and can be preprocessed with the prefix sum.
The second Sigma: i+1 is also unchanged. Use the tree array to count the difference changes and then sum them. The
third Sigma: need to open up another tree The array idel counts the prefix sum of i*del[xi] and
then when we modify the interval segment, we need to pair idel[s] + add * s for the difference array del[s]+add at the same time because the last sigma is to indicate that the difference is to be paired Each modification of the array is multiplied by the modified position/[subscript],
and then sigma (del[xi]*xi) is naturally calculated when the cumulative sum is calculated.

code:

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long ll;
const int maxn = 1e5+10;
ll a[maxn],Sum[maxn],del[maxn],idel[maxn];
// 树状数组 区间更新 区间修改
//维护三个树状数组 1 原始树状数组 
//                 2 差分树状数组 del
//                 3 i*del[i] 的树状数组
int n,m;
void update(ll a[],int x,int add){
    while(x<=n){
        a[x]+=add;
        x+=x&(-x);
    }
}
ll sum(ll a[],int x){
    ll s1=0;
    int tmp = x;
    while(tmp>0){
        s1+=a[tmp];
        tmp-=tmp&(-tmp);
    }
    return s1;
}
int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cin>>n>>m;
    for(int i=1;i<=n;i++)
    {
        cin>>a[i];
        Sum[i] = Sum[i-1]+a[i];
    }
    while(m--){
        string o;
        int s,e,add;
        cin>>o;
        if(o[0]=='Q'){
            cin>>s>>e;
            ll ss = Sum[s-1] + s*sum(del,s-1) - sum(idel,s-1); 
            ll se = Sum[e] + (e+1)*sum(del,e) - sum(idel,e);
            cout<<se-ss<<endl;
        }
        else{
            cin>>s>>e>>add;
            //维护区间差分数组 求和时需要用 (x+1)*Sigma(del[x]) 
            update(del,s,add);
            update(del,e+1,-add);
            //维护需要减去的 i*del[i]数组 求和时需要减去 Sigma(i*del[i]) 
            update(idel,s,s*add);
            update(idel,e+1,(e+1)*(-add));
        }
    } 
    return 0;
} 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325732194&siteId=291194637