题意:给一串数字,有区间加减和求和操作。
思路:线段树区间加减,区间求和。注意要用longlong。模版题。
#include <cstdio> #include <cstring> using namespace std; typedef long long LL; const int maxn=100005<<2; struct LineTree { LL sum[maxn],tar[maxn]; void build(int o,int L,int R) { tar[o]=0; if(L==R) scanf("%lld",&sum[o]); else { int M=L+(R-L)/2; build(o<<1,L,M); build(o<<1|1,M+1,R); push_up(o); } } void push_up(int o) { sum[o]=sum[o<<1]+sum[o<<1|1]; } void push_down(int o,int m) { if(tar[o]) { tar[o<<1]+=tar[o]; tar[o<<1|1]+=tar[o]; sum[o<<1]+=tar[o]*(m-m/2); sum[o<<1|1]+=tar[o]*(m/2); tar[o]=0; } } void add(int o,LL c,int ql,int qr,int L,int R) { if(ql<=L&&R<=qr) { sum[o]+=c*(R-L+1); tar[o]+=c; } else { int M=L+(R-L)/2; push_down(o,R-L+1); if(ql<=M) add(o<<1,c,ql,qr,L,M); if(M<qr) add(o<<1|1,c,ql,qr,M+1,R); push_up(o); } } LL query(int o,int ql,int qr,int L,int R) { if(ql<=L&&R<=qr) return sum[o]; else { LL s=0; int M=L+(R-L)/2; push_down(o,R-L+1); if(ql<=M) s+=query(o<<1,ql,qr,L,M); if(M<qr) s+=query(o<<1|1,ql,qr,M+1,R); return s; } } }; LineTree tree; int main() { int n,m; while(scanf("%d%d",&n,&m)!=EOF) { tree.build(1,1,n); while(m--) { char s[5]; scanf("%s",s); if(s[0]=='Q') { int a,b; scanf("%d%d",&a,&b); printf("%lld\n",tree.query(1,a,b,1,n)); } else { int a,b; LL c; scanf("%d%d%lld",&a,&b,&c); tree.add(1,c,a,b,1,n); } } } return 0; }