树状数组

前言

我好菜啊,竟然不会树状数组区间加的操作。

讲解

普通树状数组

对于原数列 (a),树状数组 (t[n]=sum_{i={n-lowbit(n)}+1}^n a[i])

进阶树状数组

考虑差分实现区间加和询问

(t[n]=a[n]-a[n-1]Rightarrow a[n]=sum_{i=1}^n t[i])

(sum_{i=1}^na[i]=sum_{i=1}^n(n-i+1)t[i]=n*sum_{i=1}^nt[i]-sum_{i=1}^n(i-1)*t[i])

真不戳,看代码吧~

练习

板题(洛谷)

代码

LL t1[MAXN],t2[MAXN];
int lowbit(int x){return (x & -x);}
void Add(int x,LL val){for(int i = x;i <= n;i += lowbit(i)) t1[i] += val,t2[i] += (x-1) * val;}
void Add(int l,int r,LL val){Add(l,val); Add(r+1,-val);}
LL Sum(int x){LL ret = 0;for(int i = x;i >= 1;i -= lowbit(i)) ret += x * t1[i] - t2[i];return ret;}//前缀和!
LL Sum(int l,int r){return Sum(r) - Sum(l-1);}

int main()
{
//	freopen(".in","r",stdin);
//	freopen(".out","w",stdout);
	n = Read(); m = Read();
	for(int i = 1;i <= n;++ i) Add(i,i,Read());
	while(m --> 0)
	{
		int opt = Read(),l = Read(),r = Read();
		if(opt == 1) Add(l,r,Read());
		else Put(Sum(l,r),'
');
	}
	return 0;
}
原文地址:https://www.cnblogs.com/PPLPPL/p/14409820.html