题目大意:
给定一个长度为N的数列,输入Q行操作指令。指令有两种:
1.“C l r d”,区间A[l~r]都加上d
2.“Q l r”,查询区间A[l~r]每个数的和并输出
解题思路:
线段树模板啊~~~~
Accepted code:
#include<cstdio>
#include<algorithm>
#define ls (now<<1)
#define rs (now<<1|1)
#define l(x) tree[x].l
#define r(x) tree[x].r
#define S(x) tree[x].sum
#define A(x) tree[x].lazy
#define N 100010
#define mid(x,y) ((x+y)>>1)
using namespace std;
struct Segment_Tree {
int l,r;
long long sum,lazy;
}tree[N<<2];
int a[N],n,m;
void build(int now,int l,int r) {
l(now)=l; r(now)=r;
if (l==r) {scanf("%lld",&S(now));return;}
build(ls,l,mid(l,r));
build(rs,mid(l,r)+1,r);
S(now)=S(ls)+S(rs);
}
void down_update(int now) {
if (A(now)) {
S(ls)+=A(now)*(r(ls)-l(ls)+1); A(ls)+=A(now);
S(rs)+=A(now)*(r(rs)-l(rs)+1); A(rs)+=A(now);
A(now)=0;
}
}
void change(int now,int l,int r,int d) {
if (l<=l(now)&&r>=r(now)) {
S(now)+=(long long)d*(r(now)-l(now)+1);
A(now)+=d; return;
}
down_update(now); int mi=mid(l(now),r(now));
if(l<=mi) change(ls,l,r,d);
if(r>mi) change(rs,l,r,d);
S(now)=S(ls)+S(rs);
}
long long ask(int now,int l,int r) {
if (l<=l(now)&&r>=r(now)) return S(now);
down_update(now);
int mi=mid(l(now),r(now));
long long All=0;
if (l<=mi) All+=ask(ls,l,r);
if (r>mi) All+=ask(rs,l,r);
return All;
}
int main() {
scanf("%d%d",&n,&m);
build(1,1,n);
while (m--) {
char c[2];int x,y,dat;
scanf("%s%d%d",c,&x,&y);
if (c[0]=='C') {
scanf("%d",&dat);
change(1,x,y,dat);
} else printf("%lld\n",ask(1,x,y));
}
}