树状数组进阶

CSDN同步

前置知识:

  • 树状数组单点修改,区间修改。

  • 差分。

下面我们考虑区间修改。

一开始我们维护的是部分前缀和,但是现在,区间修改显然不能用前缀和有关的做法。

单区间修改用差分就够了。但是这里有修改,考虑将 差分树状数组 结合。

\(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 \times \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;
posted @ 2020-08-19 15:38  bifanwen  阅读(127)  评论(1编辑  收藏  举报