区间修改?普通树状数组只支持单点修改&查询前缀和(因此也可以求区间和)
考虑用树状数组维护差分序列.
在原序列上$a[l,r]+=k$在差分序列上转化为$c[l]+=k,c[r+1]-=k$
而对差分序列求前缀和即可恢复原序列(即$(\sum_{i=1}^x c[i]) = a[x]$)
于是,区间修改&单点查询操作即转化为单点修改&查询前缀和
另外,如果不对原序列进行差分,直接在输出时加上$a[x]$也是可以的
//Wan Hong 3.0
//notebook
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <queue>
typedef long long ll;
typedef std::pair<ll,ll> pll;
ll read()
{
ll x=0,f=1;
char c=getchar();
while(c<'0'||c>'9')
{
if(c=='-')f=-1;
c=getchar();
}
while(c>='0'&&c<='9')x=x*10+c-'0',c=getchar();
return f*x;
}
ll min(ll a,ll b)
{
return a<b?a:b;
}
ll max(ll a,ll b)
{
return a>b?a:b;
}
bool umin(ll &a,ll b)
{
if(b<a)return a=b,1;
return 0;
}
bool umax(ll &a,ll b)
{
if(b>a)return a=b,1;
return 0;
}
ll abs(ll x)
{
return x>0?x:-x;
}
/**********/
#define MAXN 100011
ll n,m;
struct BIT
{
ll t[MAXN];
#define lowb (i&-i)
void modify(ll i,ll k)
{
while(i<=n)
{
t[i]+=k;
i+=lowb;
}
}
ll Qsum(ll i)
{
ll res=0;
while(i)
{
res+=t[i];
i-=lowb;
}
return res;
}
}t;
ll a[MAXN];
int main()
{
n=read(),m=read();
for(ll i=1;i<=n;++i)a[i]=read();
for(ll i=1;i<=m;++i)
{
char op=getchar();
while(op!='Q'&&op!='C')op=getchar();
if(op=='Q')
{
ll x=read();
printf("%lld\n",t.Qsum(x)+a[x]);
}
else
{
ll l=read(),r=read(),k=read();
t.modify(l,k);t.modify(r+1,-k);
}
}
return 0;
}