- lyd写法
/*
Name: SegmentTree
Author: Jack
Date: 09/04/19 19:40
*/
#include<iostream>
#include<cstdio>
#define ls(p) p*2//左子树编号
#define rs(p) ls(p)+1//右子树编号
#define md(x,y) (x+y)>>1//平均值
using namespace std;
const int maxn = 100000 + 10;
struct Segmenttree {
int l, r;//左边界,右边界
long long sum, add;//区间和,延迟标记
#define l(x) tree[x].l
#define r(x) tree[x].r
#define sum(x) tree[x].sum
#define add(x) tree[x].add
} tree[maxn * 4];
int a[maxn], n, m;
void bulid(int p, int l, int r) {
//建造树
l(p) = l, r(p) = r;
//左为左,右为右
if(l == r) {
sum(p) = a[l];
return ;
//如果已经分到了最小段(单节点),则其区间和为其数值
}
int mid = md(l,r);
bulid(ls(p), l, mid);//建造左子树
bulid(rs(p), mid + 1, r);//建造右子树
sum(p) = sum(ls(p)) + sum(rs(p));//区间和为左右子树和之和
}
void spread(int p) {
if(add(p)) {
sum(ls(p)) += add(p) * (r(ls(p)) - l(ls(p)) + 1);
sum(rs(p)) += add(p) * (r(rs(p)) - l(rs(p)) + 1);
//左子树之和+=延迟标记*左子树子节点个数,右子树同理
add(ls(p)) += add(p);
add(rs(p)) += add(p);
//下传一层标记
add(p) = 0;
//清空原标记
}
}
void change(int p, int l, int r, int d) {
if(l <= l(p) && r >= r(p)) {
//由线段树性质可得,当以上条件都满足时,[l,r]必然为一个子树
sum(p) += (long long)d * (r(p) - l(p) + 1);//加sum
add(p) += d;//做标记
return ;
}
spread(p);
int mid = md(l(p),r(p));
if(l <= mid)change(ls(p), l, r, d);
if(r > mid)change(rs(p), l, r, d);
//将此不可直接解区间转化为可解或不可解系数低的区间
sum(p) = sum(ls(p)) + sum(rs(p));//求和
}
long long ask(int p, int l, int r) {
if(l <= l(p) && r >= r(p))return sum(p);
//同change函数
spread(p);
int mid = md(l(p),r(p));
long long val = 0;
if(l <= mid)val += ask(ls(p), l, r);
if(r > mid)val += ask(rs(p), l, r);
//类似于change,将不可直接解区间转化为可解或不可解系数低的区间
return val;
}
int main() {
cin >> n >> m;
for(int i = 1; i <= n; i++) {
scanf("%d", &a[i]);
}
bulid(1, 1, n);//在编号为1的子树,[1,n]区间内建造树
while(m--) {
int opt, l, r, d;
scanf("%d%d%d", &opt, &l, &r);
if(opt == 1) {
scanf("%d", &d);
change(1, l, r, d);
} else
printf("%lld\n", ask(1, l, r));
}
return 0;
}
- 廖哥写法
/*
Name: SegmentTree
Author: Jack
Date: 09/04/19 19:43
*/
#include<iostream>
#include<cstdio>
#include<cmath>
#define ls(h) h<<1
#define rs(h) h<<1|1
const int maxn=100000+10;
using namespace std;
long long c[maxn*4],sum,lazy[maxn*4];
void init(int h,int s,int t){
int mid=(s+t)>>1;
if(s==t)scanf("%d",&c[h]);
else{
init(ls(h),s,mid);
init(rs(h),mid+1,t);
c[h]=c[ls(h)]+c[rs(h)];
}
}
void pushdown(int h,int s,int t,int num){
c[h]+=(t-s+1)*num;
lazy[h]+=num;
}
void gx(int h,int s,int t,int L,int R,int num){
int mid=(s+t)>>1;
if(L<=s && t<=R){
c[h]+=(t-s+1)*num;
lazy[h]+=num;
}else{
if(lazy[h]){
pushdown(ls(h),s,mid,lazy[h]);
pushdown(rs(h),mid+1,t,lazy[h]);
lazy[h]=0;
}
if(L<=mid)gx(ls(h),s,mid,L,R,num);
if(mid<R)gx(rs(h),mid+1,t,L,R,num);
c[h]=c[ls(h)]+c[rs(h)];
}
}
void cx(int h,int s,int t,int L,int R){
int mid=(s+t)>>1;
if(L<=s && t<=R)sum+=c[h];
else{
if(lazy[h]){
pushdown(ls(h),s,mid,lazy[h]);
pushdown(rs(h),mid+1,t,lazy[h]);
lazy[h]=0;
}
if(L<=mid)cx(ls(h),s,mid,L,R);
if(mid<R)cx(rs(h),mid+1,t,L,R);
}
}
int main(){
int i,j,k,m,n,x,y,z;
cin>>n>>m;
init(1,1,n);
for(i=1;i<=m;i++){
scanf("%d",&k);
if(k==1){
scanf("%d%d%d",&x,&y,&z);
gx(1,1,n,x,y,z);
}else{
scanf("%d%d",&x,&y);
sum=0;
cx(1,1,n,x,y);
printf("%lld\n",sum);
}
}
return 0;
}