下面的题解转于传送门
对于想要学习区间修改和单点输出的同学们可以去看这篇文章
传送门
假设数组a是原数组,b是a的差分数组,由前缀和的定义,我们求前n个元素的和,即
详细过程如下:
a1 + a2 + ... + an = b1 + (b1 + b2) + ....+ (b1 + b2 + b3 + ... bn) ->n * b1 + (n - 1) * b2 + ... + bn
所以我们要先对原数组a进行差分,得到差分数组b,才对b[i]和b[i]*i分别维护一个树状数组tb和tc,
而l到r的和变为
[(r + 1) * sum(tb, r) - sum(tc, r)]-[(l + 1) * sum(tb, l) - sum(tc, l)]
代码
#include <bits/stdc++.h> using namespace std; typedef long long ll; typedef __int128 LL; const int maxn = 100000 + 5; const int Mod = 1e9 + 7; ll a[maxn],b[maxn],tb[maxn],tc[maxn]; //b为差分数组,tb为b[i] 要维护的树状数组,tc为要树状数组维护的b[i] * i; int n,m; inline int lowbit(int x) { return x & (-x); } void add(int x,ll v) { ll val = x * v; for(int i = x; i <= n; i += lowbit(i)){ tb[i] += v; tc[i] += val; } } void chafen_add(int l,int r,ll val) { add(l,val); add(r + 1,-val); } ll Query(ll a[], int x) { ll res = 0; for(int i = x; i > 0; i -= lowbit(i)){ res += a[i]; } return res; } ll Query_sum(int x) { return (x + 1) * Query(tb,x) - Query(tc ,x); } ll Q_of_Q_sum(int l,int r) { return Query_sum(r) - Query_sum(l - 1); } int main() { std::ios::sync_with_stdio(false); cin>>n>>m; for(int i = 1; i <= n; i++){ cin>>a[i]; b[i] = a[i] - a[i - 1]; add(i,b[i]); } char s[2]; while(m--){ cin>>s; if(s[0] == 'Q'){ int l,r; cin>>l>>r; ll res = Q_of_Q_sum(l,r); cout<<res<<endl; } else{ ll x,y,z; cin>>x>>y>>z; chafen_add(x,y,z); } } }