【树状数组】单点修改,区间查询 洛谷P3374_搂鱼114514的博客-CSDN博客
P3368 【模板】树状数组 2 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
题意
接上一篇题解,这一题由“单点修改,区间查询”变成了“区间修改,单点查询”。
思路
此时我们要引入一个知识点:差分
差分数组cha,使得,其中,
那么不难发现,。
差分数组的一个性质:对一个区间增减某个值的时候,差分数组的区间左端点值会同步变化,而其右端点后一个值会产生相反地变化,其他点不变。因此在更新区间时,增加那么就要相反的减去。
void addpoint(ll x,ll k)
{
for(int i=x;i<=n;i+=lowbit(i))
a[i]+=k;
}
······
cin>>x>>y>>k;
addpoint(x,k);
addpoint(y+1,-k);
求只需要将差分数组的前i个值相加
ll chaxun(ll y)
{
ll ans=0;
for(int i=y;i>=1;i-=lowbit(i))
ans+=a[i];
return ans;
}
代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const ll z=5000005;
ll n,m,zt,x,y,a[z],k,c[z],cha;
void fastread()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
}
ll lowbit(ll x)
{
return x&(-x);
}
void addpoint(ll x,ll k)
{
for(int i=x;i<=n;i+=lowbit(i))
a[i]+=k;
}
ll chaxun(ll y)
{
ll ans=0;
for(int i=y;i>=1;i-=lowbit(i))
ans+=a[i];
return ans;
}
int main()
{
fastread();
cin>>n>>m;
for(int i=1;i<=n;i++)
{
cin>>c[i];
cha=c[i]-c[i-1];
addpoint(i,cha);
}
for(int i=1;i<=m;i++)
{
cin>>zt;
if(zt==1)
{
cin>>x>>y>>k;
addpoint(x,k);
addpoint(y+1,-k);
}
if(zt==2)
{
cin>>x;
cout<<chaxun(x)<<endl;
}
}
return 0;
}