原题链接:传送门
题意:有n个数,m次操作。输一个字符,当字符为Q时,查询a到b的总和,为C时表示从a到b加上c。
线段树简单区间更新。
#include <iostream>
#include <cstring>
#include <cstdio>
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
using namespace std;
typedef long long ll;
const int N = 100005;
ll num[N<<2],lazy[N<<2];
void PushUp(ll rt) {
num[rt] = num[rt<<1] + num[rt<<1|1];
}
void PushDown(ll rt,ll len) {
if(lazy[rt]) {
lazy[rt<<1] += lazy[rt]; //向下传
lazy[rt<<1|1] += lazy[rt];
num[rt<<1] += lazy[rt] * (len - (len>>1)); //向下更新。。
num[rt<<1|1] += lazy[rt] * (len>>1);
lazy[rt] = 0; //清除标记
}
}
void Build(ll l,ll r,ll rt) {
lazy[rt] = 0;
if(l == r) {
scanf("%lld",&num[rt]);
return ;
}
ll m = (r-l)/2 + l;
Build(lson);
Build(rson);
PushUp(rt);
}
void Updata(ll L,ll R,ll val,ll l,ll r,ll rt) {
if(L <= l && r <= R) {
num[rt] += val*(r-l+1); //加上 val*区间长度 即为num[rt]的增值
lazy[rt] += val; //标记 +val
return ;
}
PushDown(rt,r-l+1); //向下更新
ll m = (r-l)/2 + l;
if(L <= m) Updata(L,R,val,lson);
if(R > m) Updata(L,R,val,rson);
PushUp(rt);
}
ll Query(ll L,ll R,ll l,ll r,ll rt) {
if(L <= l && r <= R) {
return num[rt];
}
PushDown(rt,r-l+1);
ll ret = 0;
ll m = (r-l)/2 + l;
if(L <= m) ret += Query(L,R,lson);
if(R > m) ret += Query(L,R,rson);
return ret;
}
int main() {
ll n,m;
scanf("%lld%lld",&n,&m);
Build(1,n,1);
for(int i=0; i<m; i++) {
char ch;
ll a,b,c;
getchar();
scanf("%c",&ch);
if(ch == 'Q') {
scanf("%lld%lld",&a,&b);
printf("%lld\n",Query(a,b,1,n,1));
} else {
scanf("%lld%lld%lld",&a,&b,&c);
Updata(a,b,c,1,n,1);
}
}
return 0;
}