链接:P3368
这里需要首先知道差分思想的利用
如果有一个数组为
a[5]={1,4,3,2,5};
那么则他的差分数组为
b[5]={1,3,-1,-1,3}
我们这里可以发现
对于任意的Ai 他的值就等于B1+B2+…+Bi
那么我们便可以利用这个思想
来进行区间同时加一个数
若现在我们要在[x,y]进行同时加上一个数k
那么我们便可以利用差分数组b
在b[x]的地方加上k
在b[y+1]的地方减去k
十分容易理解,在此我就不放出证明过程了(懒癌终极患者)
那么我们既然要求的是区间加和区间和
若用线段树十分好解决(就是代码长一点)
如果用树状数组解决,我们显然不可以直接加减,因为树状数组一次只能对一个点进行增减。
那么我们便可以利用差分数组,我们用树状数组来维护一个差分数组就可以实现区间加和区间求和的过程了
加入一个数的操作和查找操作都与原本相同
就是在输入输出判断等地方的时候改了一下
代码:
#include <cstdio>
#include <iostream>
using namespace std;
int n,m,a[1000001],aa[1000001],flag;
int lowbit(int i)
{
return i&(-i);
}
void add(int i,int x)
{
while (i<=n)
{
a[i]+=x;
i+=lowbit(i);
}
}
long long pd(int i)
{
long long ans=0;
while (i!=0)
{
ans+=a[i];
i-=lowbit(i);
}
return ans;
}
int main()
{
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++)
{
int a;
scanf("%d",&aa[i]);
// add(i,aa[i]);
}
for (int i=1;i<=m;i++)
{
scanf("%d",&flag);
if (flag==1)
{
int x,y,k;
scanf("%d%d%d",&x,&y,&k);
add(x,k);
add(y+1,-k); //差分思想
}
if (flag==2)
{
int x,y;
scanf("%d",&x);
printf("%lld\n",aa[x]+pd(x));
}
}
return 0;
}