区间更新和查询
区间更新要延迟更新,就是当某结点完全处于要更新的区间之中时,我们只更新到该结点,并把其子结点要更新的值记录在本结点,当要向下更新或查询时再进行更新
#include<stdio.h>
#include<string.h>
//typedef long long ll;
typedef __int64 ll;
#define N 100005
struct Node{
int l,r;
ll sum,add;
}t[N*4];
void build(int cur,int l,int r){
t[cur].l=l;
t[cur].r=r;
t[cur].sum=0;
t[cur].add=0;
if(l==r) return;
int mid=(l+r)>>1;
build(cur*2,l,mid);
build(cur*2+1,mid+1,r);
}
void pushdown(int cur){
t[cur*2].sum+=(t[cur*2].r-t[cur*2].l+1)*t[cur].add;
t[cur*2+1].sum+=(t[cur*2+1].r-t[cur*2+1].l+1)*t[cur].add;
t[cur*2].add+=t[cur].add;
t[cur*2+1].add+=t[cur].add;
t[cur].add=0;
}
void pushup(int cur){
t[cur].sum=t[cur*2].sum+t[cur*2+1].sum;
}
void update(int cur,int l,int r,ll num){
if(t[cur].r<l||t[cur].l>r) return;
if(t[cur].l>=l && r>=t[cur].r){
t[cur].sum+=(t[cur].r-t[cur].l+1)*num;
t[cur].add+=num;
//printf("%I64d\n",t[cur].sum);
return;
}
pushdown(cur);
int mid=(l+r)>>1;
update(cur*2,l,r,num);
update(cur*2+1,l,r,num);
pushup(cur);
}
ll query(int cur,int l,int r){
if(t[cur].r<l||t[cur].l>r) return 0;
if(l<=t[cur].l&&t[cur].r<=r) {
return t[cur].sum;
}
pushdown(cur);
return query(cur*2,l,r)+query(cur*2+1,l,r);
}
int main(){
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
#endif
int n,q;
scanf("%d%d",&n,&q);
int tmp,i;
build(1,1,n);
for(i=1;i<=n;i++){
scanf("%d",&tmp);
update(1,i,i,tmp);
}
//printf("%I64d\n",t[1].sum);
char c[10];//为了防止有接收空格的情况出现,用数组接收
for(i=0;i<q;i++){
scanf("%s",c);
int tmp1,tmp2,tmp3;
//printf("%s\n",c);
if(c[0]=='Q'){
scanf("%d%d",&tmp1,&tmp2);
printf("%I64d\n",query(1,tmp1,tmp2));
}
else {
scanf("%d%d%d",&tmp1,&tmp2,&tmp3);
update(1,tmp1,tmp2,tmp3);
}
}
return 0;
}