题目链接 https://cn.vjudge.net/problem/POJ-3468
【题意】
给定长度为
N
N
N 的序列
A
A
A,有
Q
Q
Q次操作,操作分两种
C
a
b
c
C \ a \ b \ c
C a b c 表示将序列中
A
[
a
,
b
]
A[a,b]
A[a,b]所有元素都加上一个数字
c
c
c
Q
a
b
Q \ a \ b
Q a b 表示查询序列
A
[
a
,
b
]
A[a,b]
A[a,b] 的元素之和
(
N
,
Q
<
=
1
0
5
,
∣
A
i
∣
<
=
1
0
9
)
(N,Q<=10^5,|A_i|<=10^9)
(N,Q<=105,∣Ai∣<=109)
【思路】
线段树区间更新,维护区间和并用lazy标记进行区间更新
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define node tree[id]
#define lson tree[id<<1]
#define rson tree[id<<1|1]
using namespace std;
typedef long long ll;
const int maxn=100005;
struct Tree{
int left,right;
ll sum,lazy;
}tree[maxn<<2];
int n,q;
ll a[maxn];
void pushup(int id){node.sum=lson.sum+rson.sum;}
void pushdown(int id){
if(node.lazy && node.left!=node.right){
lson.lazy+=node.lazy;
lson.sum+=node.lazy*(ll)(lson.right-lson.left+1);
rson.lazy+=node.lazy;
rson.sum+=node.lazy*(ll)(rson.right-rson.left+1);
node.lazy=0;
}
}
void build(int id,int le,int ri){
node.left=le;
node.right=ri;
node.lazy=0;
if(le==ri){
node.sum=a[le];
return;
}
int mid=(le+ri)>>1;
build(id<<1,le,mid);
build(id<<1|1,mid+1,ri);
pushup(id);
}
ll query(int id,int le,int ri){
if(node.left==le && node.right==ri){
return node.sum;
}
pushdown(id);
int mid=(node.left+node.right)>>1;
if(ri<=mid) return query(id<<1,le,ri);
else if(le>mid) return query(id<<1|1,le,ri);
else return query(id<<1,le,mid)+query(id<<1|1,mid+1,ri);
}
void update(int id,int le,int ri,ll val){
if(node.left==le && node.right==ri){
node.sum+=val*(ll)(node.right-node.left+1);
node.lazy+=val;
return;
}
pushdown(id);
int mid=(node.left+node.right)>>1;
if(ri<=mid) update(id<<1,le,ri,val);
else if(le>mid) update(id<<1|1,le,ri,val);
else{
update(id<<1,le,mid,val);
update(id<<1|1,mid+1,ri,val);
}
pushup(id);
}
int main(){
while(scanf("%d%d",&n,&q)==2){
for(int i=1;i<=n;++i) scanf("%lld",&a[i]);
build(1,1,n);
while(q--){
char op[2];
scanf("%s",op);
if(op[0]=='Q'){
int a,b;
scanf("%d%d",&a,&b);
printf("%lld\n",query(1,a,b));
}
else{
int a,b;
ll c;
scanf("%d%d%lld",&a,&b,&c);
update(1,a,b,c);
}
}
}
return 0;
}