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