树状数组 :区间修改,区间查询

树状数组:区间修改,区间查询树状数组 :区间修改,区间查询

一、树状数组是什么?

新手请参考 ————》》————》》

树状数组 数据结构详解与模板(可能是最详细的了)

夜深人静写算法(十三)- 树状数组

二、区间修改与区间查询

凡是涉及到区间修改,就必须用到 差分差分

求前缀和:

  • apa_p 的前缀和:i=1pa[i]=i=1pj=1id[j]\sum_{i=1}^{p}a[i]=\sum_{i=1}^{p}\sum_{j=1}^{i}d[j]

  • i=1pj=1id[j]\sum_{i=1}^{p}\sum_{j=1}^{i}d[j]中,d1d_1 被用了 pp 次,d2d_2 被用了 p1p-1 次……那么我们

    可以写出:

    apa_p 的前缀和:i=1pj=1id[j]=i=1pd[i]×(pi+1)=(p+1)×i=1pd[i]i=1pd[i]×i\sum_{i=1}^{p}\sum_{j=1}^{i}d[j]=\sum_{i=1}^{p}d[i]\times(p-i+1)= \\ \\ \\ \\(p+1)\times\sum_{i=1}^{p}d[i]-\sum_{i=1}^{p}d[i]\times i

  • 那么我们可以用树状数组维护两个数组的前缀和:一个数组是 sum1[i]=d[i]sum1[i]=d[i],另一个数组是 sum2[i]=d[i]×isum2[i]=d[i]\times i

区间修改区间修改

对于 t1t1 数组的修改同上对 dd 数组的修改。

对于 t2t2 数组的修改也类似,我们给 t2[l]t2[l] 加上 l×xl \times x,给 t2[r+1]t2[r + 1] 减去 (r+1)×x(r + 1) \times x

ACcodeAC code

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int maxn=1e6+5;
int n,q,a[maxn],maxx,b[maxn],c[maxn];

inline int lowbit(int a)
{
	return a&(-a);
}
inline void update(int x,int y)
{
	for(int i=x;i<=n;i+=lowbit(i))
	{
		b[i]+=y;
		c[i]+=x*y;
	}
}
inline void range_update(int l,int r,int x)
{
	update(l,x);
	update(r+1,-x);
}
inline int query(int x)
{
	int ans=0;
	for(int i=x;i;i-=lowbit(i))
	{
		ans += (x+1) * b[i] - c[i];
	}
	return ans;
}
inline int range_query(int l,int r)
{
	return query(r)-query(l-1);
}
signed main()
{
	cin>>n>>q;
	for(int i=1;i<=n;i++)
	{
		cin>>a[i];
		update(i,a[i]-a[i-1]);
	}
	for(int i=1;i<=q;i++)
	{
		int abc,x,y,z;
		cin>>abc;
		if(abc==1)
		{
			cin>>x>>y>>z;
			range_update(x,y,z);
		}
		else
		{
			cin>>x>>y;
			cout<<range_query(x,y)<<endl;
		}
	}
	return 0;
}
posted @ 2021-05-11 20:41  蒟蒻orz  阅读(13)  评论(0编辑  收藏  举报  来源