题目链接
这是LibreOJ上的树状数组模板题,这题考查的是区间修改和单点查询,运用到了差分思想,在此附上一版AC代码:
#include<iostream>
using namespace std;
typedef long long ll;
ll b[1000005], bb[1000005], a[1000005];
//a是原数组,b是a的差分数组,bb是维护b的树状数组。
ll n, q;
ll lowbit(ll x){
return x & (-x);
}
void creat(){
for(ll i=1;i<=n;i++){
bb[i]+=b[i];
ll j=i+lowbit(i);
if(j<=n) bb[j]+=bb[i];
}
}
//建树。
ll getsum(ll x){
ll ans=0;
while(x>=1){
ans+=bb[x];
x-=lowbit(x);
}
return ans;
}
//求前缀和。
void add(ll x, ll k){
while(x<=n){
bb[x] += k;
x += lowbit(x);
}
}
//单点修改。区间修改因为差分思想可转变为俩个单点修改。
int main()
{
scanf("%lld%lld", &n, &q);
for(int i=1;i<=n;i++){
scanf("%lld", &a[i]);
if(i==1){
b[1]=a[1];
}else{
b[i]=a[i]-a[i-1];
}
}
creat();
ll flag;
ll l, r, x;
ll y;
for(int i=1;i<=q;i++){
scanf("%lld", &flag);
if(flag==2){
scanf("%lld", &y);
printf("%lld\n", getsum(y));
}else {
scanf("%lld%lld%lld", &l, &r, &x);
add(l, x);
if(r!=n){
add(r+1, -x);
}
}
}
return 0;
}