推荐一篇博客:
http://m.blog.csdn.net/blackjack_/article/details/74997479
推导过程在代码之前,模板题是Luogu 3368或者codevs线段树练习3
/*
pre_sum(n)=a[1]+a[2]+...+a[n]
=c[1]+(c[1]+c[2])+...+(c[1]+c[2]+...+c[n])
=n*(c[1]+c[2]+...+c[n])-(0*c[1]+1*c[2]+...+(n-1)*c[n])
令d[i]=(i-1)*c[i]
modify(l,r,+v):
add(c,l,v),add(c,r+1,-v),add(d,l,(l-1)*v),add(d,r+1,-r*v)
pre_sum(n)=n*query(c,n)-query(d,n)
sum(l,r)=pre_sum(r)-pre_sum(l-1)
*/
#include
using namespace std;
const int MAXN=5e5+2;
int n,m,c[MAXN],d[MAXN];
inline int read() {
int 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 x*f;
}
inline void add(int *r,int pos,int v) {
for (int i=pos;i<=n;i+=(i&-i))
r[i]+=v;
}
inline int query(int *r,int pos) {
int ret=0;
for (int i=pos;i;i-=(i&-i))
ret+=r[i];
return ret;
}
int main() {
// freopen("P3368.in","r",stdin);
memset(c,0,sizeof(c)),
memset(d,0,sizeof(d));
n=read(),m=read();
for (register int i=1;i<=n;++i) {
int v=read();
add(c,i,v),add(c,i+1,-v),add(d,i,(i-1)*v),add(d,(i+1),-i*v);
}
for (register int i=1;i<=m;++i) {
int opt=read();
if (opt&1) {
int l=read(),r=read(),v=read();
add(c,l,v),add(c,r+1,-v),add(d,l,(l-1)*v),add(d,(r+1),-r*v);
}
else {
int pos=read(),l=pos-1,r=pos;
int t1=r*query(c,r)-query(d,r),t2=l*query(c,l)-query(d,l);
printf("%d\n",t1-t2);
}
}
return 0;
}