思路:线断树模版题(带延迟更新lazy),注意sum要用long long
代码:
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<vector>
#include<algorithm>
using namespace std;
#define LL(x) (x<<1)
#define RR(x) (x<<1|1)
const int MAXN=1e5+2;
struct node{
int le,ri;
long long val;
long long addMark; // 延迟标记
int mid(){
return (le+ri)>>1;
}
}tree[MAXN<<2];
int n,m;
int a[MAXN];
void build(int root,int le,int ri){
tree[root].addMark=0;
tree[root].le=le;
tree[root].ri=ri;
if(le==ri){
tree[root].val=a[le];
return ;
}
int mid=tree[root].mid();
build(LL(root), le, mid);
build(RR(root), mid+1, ri);
tree[root].val=tree[LL(root)].val+tree[RR(root)].val;
}
void pushDown(int root){
if(tree[root].addMark!=0){
// 设置左右孩子节点的标志域
tree[LL(root)].addMark+=tree[root].addMark;
tree[RR(root)].addMark+=tree[root].addMark;
// 根据标志域设置孩子节点的值
tree[LL(root)].val+=tree[root].addMark*(tree[LL(root)].ri-tree[LL(root)].le+1);
tree[RR(root)].val+=tree[root].addMark*(tree[RR(root)].ri-tree[RR(root)].le+1);
// 传递后,当前节点标记域清空
tree[root].addMark=0;
}
}
void update(int root,int le,int ri,int num){
if(le<=tree[root].le&&tree[root].ri<=ri){
tree[root].addMark+=num;
tree[root].val+=num*(tree[root].ri-tree[root].le+1);
return ;
}
if(tree[root].le!=tree[root].ri)
pushDown(root);
int mid=tree[root].mid();
if(le<=mid)
update(LL(root),le,ri,num);
if(ri>mid)
update(RR(root),le,ri,num);
tree[root].val=tree[LL(root)].val+tree[RR(root)].val;
}
long long query(int root,int le,int ri){
if(le<=tree[root].le&&tree[root].ri<=ri)
return tree[root].val;
pushDown(root);
int mid=tree[root].mid();
if(le>mid)
return query(RR(root), le, ri);
else if(ri<=mid)
return query(LL(root), le, ri);
else
return query(LL(root), le, ri)+query(RR(root), le, ri);
}
int main(){
scanf("%d %d",&n,&m);
for(int i=1;i<=n;++i)
scanf("%d",&a[i]);
build(1, 1, n);
int op;
int x,y,k;
while(m--){
scanf("%d",&op);
if(op==1){
scanf("%d %d %d",&x,&y,&k);
update(1,x,y,k);
} else if(op==2){
scanf("%d %d",&x,&y);
printf("%lld\n",query(1, x, y));
}
}
return 0;
}