思路:线段树模板题,用add标记。具体内容可参考代码或者刘汝佳训练指南。
#include<cstdio> #include<cstring> #define MAXN 100005 typedef long long LL; LL n,Q,ql,qr,v,sumv[MAXN*3],a[MAXN],addv[MAXN*3],_sum; char op; void build(LL o,LL L,LL R) { if(L==R) {sumv[o]=a[L];return;} LL M=(L+R)>>1; build(o*2,L,M); build(o*2+1,M+1,R); sumv[o]=sumv[o*2]+sumv[o*2+1];//维护根节点 } void query(LL o,LL L,LL R,LL add) { if(ql<=L && R<=qr) {_sum+=add*(R-L+1)+sumv[o];return;} LL M=(L+R)>>1; if(ql<=M)query(o*2,L,M,add+addv[o]); if(M<qr)query(o*2+1,M+1,R,add+addv[o]); } void update(LL o,LL L,LL R) { if(ql<=L && R<=qr) {addv[o]+=v;sumv[o]+=v*(R-L+1);return;} LL M=(L+R)>>1; if(ql<=M) update(o*2,L,M); if(qr>M) update(o*2+1,M+1,R); sumv[o]=sumv[o*2]+sumv[o*2+1]+addv[o]*(R-L+1); } int main() { while(~scanf("%I64d%I64d",&n,&Q)) { for(LL i=1;i<=n;++i) scanf("%I64d",&a[i]); memset(addv,0,sizeof(addv)); build(1,1,n); while(Q--) { getchar(); op=getchar(); if(op=='Q') { scanf("%I64d%I64d",&ql,&qr); _sum=0; query(1,1,n,0); printf("%I64d\n",_sum); } else { scanf("%I64d%I64d%I64d",&ql,&qr,&v); update(1,1,n); } } } return 0; }