题目大意:
题目链接:https://www.luogu.org/problemnew/show/P3368
已知一个数列,你需要进行下面两种操作:
- 将某区间每一个数数加上
- 输出某一个数
思路:
树状数组只支持单点修改,对于区间修改,单点查询应该如和完成呢?
可以考虑前缀和。每次将一个区间加上时,就将,,这样如果将数组取前缀和,得到的就还是将区间加。
那么就可以用最基本的树状数组来求解了。
代码:
#include <cstdio>
#define ll long long
using namespace std;
int n,m,w,x,y;
ll a[500001],c[500001],z;
void add(int x,ll y) //修改
{
for (;x<=n;x+=x&-x) c[x]+=y;
}
ll ask(int x) //查询
{
ll ans=0;
for (;x;x-=x&-x) ans+=c[x];
return ans;
}
int main()
{
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
add(i,a[i]-a[i-1]); //保持前缀和为a数组
}
while (m--)
{
scanf("%d",&w);
if (w==1)
{
scanf("%d%d%d",&x,&y,&z);
add(x,z);
add(y+1,-z); //前缀和
}
else
{
scanf("%d",&x);
printf("%d\n",ask(x));
}
}
return 0;
}