树状数组的区间修改
我们假设\(a_i\) 为每一个点的本身值,\(d_i = a_i - a_{i-1}\)为差分值。
那么:
\[\sum a_x = \sum_{i=1}^x d_i\]
所以
\[\sum_{i=1}^x a_i = \sum_{i=1}^x \sum_{j=1}^i d_i = \sum_{i=1}^x (x-i+1)d_i\]
把式子拆开得:
\[\sum_{i=1}^x a_i = (x+1)\sum_{i=1}^x d_i - \sum_{i=1}^x i d_i\]
所以用两个树状数组\(c1\),\(c2\)分别维护\(d_i\) 与\(id_i\)即可。
具体的流程为:
\(Update\):把\([L,R]\)的值全部加上\(val\)
(1)\(Add(c_1, L,val )\) ; \(Add(c_1 , R+1,-val )\) ;
(2)\(Add(c_2, L,L*val )\) ; \(Add(c_2,R+1,-(R+1)*val)\) ;
._.
\(Get\):查询\([L,R]\)的元素和
(1)$Sigma(x) = (x+1)*Query(c_1,x) - Query(c_2,x) ; $
(2)$Res_{[L,R]} = Sigma(R) - Sigam(L-1) ; $
._.
代码:
IL ll Query(RG int p){
RG ll d=0 , s=(p+1);
while(p)d+= 1ll*s*c1[p]-c2[p], p-=(p&-p); return d;
}
IL int Get(int L,int R){return 1ll*Query(R) - 1ll*Query(L-1);}
IL void Add(ll *bit,int p,int d){while(p<=m)bit[p]+=d,p+=(p&-p);}
IL void Update(RG int L,RG int R,RG int dt){
Add(c1,L,dt); Add(c1,R+1,-dt);
Add(c2,L,dt*L); Add(c2,R+1,-dt*(R+1));
}