树状数组的区间修改,单点查询

前段时间处理过树状数组的单点修改,区间查询,那这次来试着搞一搞区间修改,单点查询(对,再下一次就是区间修改区间查询hhh)

首先设定一个a[ ],我们能得到一个与之相对应的差分数组b[ ],使b[i]=a[i]-a[i-1]

原数组a 3 5 2 4 8
差分数组b 3 2 -3 2 4

简单可证,a[i]=b[1]+b[2]+....+b[i]

如果我要把2,4的区间中每个数+2

原数组a 3 7 4 6 8
差分数组b 3 4 -3 2

2

发现没有?b数组只有b[2],b[5] 的值改变了,这个也很好证明的

这样我们就可以用b数组来求a数组啦,1~n求和太慢,于是我们搞一个树状数组优化一下

https://www.luogu.org/problemnew/show/P3368#sub

一道洛谷裸题

以下代码

#include
using namespace std;
int a[500010],b[500010],c[500010],n,m;
int lowbit(int x)
{
	return x&-x;
}
void modify(int x,int y)
{
	for (int i=x;i<=n;i+=lowbit(i))
		c[i]+=y;
}
int query(int x)
{
	int ans=0;
	for (int i=x;i>0;i-=lowbit(i))
		ans+=c[i];
	return ans;
}
int main()
{
	cin>>n>>m;
	for (int i=1;i<=n;i++)
	{
		scanf("%d",&a[i]);
		b[i]=a[i]-a[i-1];
	}
	for (int i=1;i<=n;i++)
		modify(i,b[i]);
	for (int i=1;i<=m;i++)
	{
		int p; 
		cin>>p;
		if (p==1)
		{
			int xx,yy,k;
			cin>>xx>>yy>>k;
			modify(xx,k);
			modify(yy+1,-k);
		}
		if (p==2)
		{
			int k;
			cin>>k;
			printf("%d\n",query(k));
		}
	}
	return 0;
}

 

你可能感兴趣的:(数据结构)