前段时间处理过树状数组的单点修改,区间查询,那这次来试着搞一搞区间修改,单点查询(对,再下一次就是区间修改区间查询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<bits/stdc++.h>
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;
}