前置知识:
-
树状数组单点修改,区间修改。
-
差分。
下面我们考虑区间修改。
一开始我们维护的是部分前缀和,但是现在,区间修改显然不能用前缀和有关的做法。
单区间修改用差分就够了。但是这里有修改,考虑将 差分 和 树状数组 结合。
令 (c) 为 (a) 的差分,维护 (a) 的区间修改与区间和即可,这样 (a) 就是 (c) 的前缀和了。
那么区间修改只需要改 (2) 个点,单点询问只需要问前缀和。但是区间询问则怎么做?
显然,还是用前缀和相减,考虑前缀和。
那么考虑一个东西:
[sum_{i=1}^n a_i
]
[= sum_{i=1}^n sum_{j=1}^i c_j
]
[= sum_{i=1}^n c_j (n-i+1)
]
[= n imes sum_{i=1}^n c_j - sum_{i=1}^n c_i (i-1)
]
显然,前面一部分我们已经得到维护,后面我们维护 (c_i (i-1)) 即可,开两个树状数组维护。
const int N=1e5+1;
int c[N],b[N];
struct BIT {
inline int lowbit(int x) {return x&(-x);}
inline int sum(int x) {
int s=0; while(x>0)
s+=c[x]*x-b[x],x-=lowbit(x);
return s;
}
inline void update(int x,int k) {
while(x<=n) c[x]+=k,x+=lowbit(x);
}
} T;