差分数组:
差分数组的思路其实是通过差分,递推出经过部分区间修改后的原数组,例如我们要对区间进行加减操作,最终求某个区间的值
举个栗子:
a[ ] | 1 | 2 | 3 | 4 | 5 |
---|---|---|---|---|---|
差分p[ ] | 1 | 1 | 1 | 1 | 1 |
修改区间:
| [1 5] +2 | [2,3] -1| [1 3] +3 |
修改后的差分p[ ] | 6 | 0 | 1 | -1 | 1 |
---|---|---|---|---|---|
修改后的a[ ] | 6 | 6 | 7 | 6 | 7 |
讲解:
我们只需要让差分数组
p[l]+=w p[r+1]-=w
我们可以通过最初的差分p[1]
得到修改后的a[]
,只需要通过递推式即可得到,由于p[1]
的差分是其本身我们就可以利用递推式得到修改后的原数组。递推式:p[i]+=p[i-1]
题解:
利用差分或者树状数组,两个树状树状比较快而且性能比较优,但是差分也可以,是种思想需要理解
AC代码:
#include<bits/stdc++.h>
using namespace std;
//差分数组
//区间和
#define ll long long
const int maxn=1000001;
ll a[maxn],p[maxn];
int main()
{
ll n,q;
//cout<<maxn;
scanf("%lld %lld",&n,&q);
for(ll i=1; i<=n; i++)
{
scanf("%lld",&a[i]);
p[i]=a[i]-a[i-1];
}
while(q--)
{
ll l,r,op,w;
scanf("%lld",&op);
if(op==1)
{
scanf("%lld %lld %lld",&l,&r,&w);
p[l]-=w;
p[r+1]+=w;
}
else
{
scanf("%lld %lld %lld",&l,&r,&w);
p[l]+=w;
p[r+1]-=w;
}
}
for(ll i=1;i<=n;i++)
{
p[i]=p[i]+p[i-1];
a[i]=a[i-1]+p[i];
}
ll l,r;
scanf("%lld %lld",&l,&r);
printf("%lld\n",a[r]-a[l-1]);
}