线段树模板

来源:互联网 发布:怎么安装ubuntu系统 编辑:程序博客网 时间:2024/06/05 05:33

// 第一个线段树,背一背

#include<iostream>

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=100010;
int n,m,a[maxn],s[maxn],c[maxn];
void push(int rt){
    s[rt]=s[rt<<1]+s[(rt<<1)|1];
}
void build(int l,int r,int rt){
    if(l==r){
        s[rt]=a[l]; return ;
    }
    int mid=(l+r)>>1;
    build(l,mid,rt<<1);
    build(mid+1,r,rt<<1|1);
    push(rt);
}
void color(int l,int r,int rt,int x){
    c[rt]+=x;
    s[rt]+=(r-l+1)*x;
}
void pushc(int l,int r,int rt){
    if(c[rt]){
        int mid=(r+l)>>1;
        color(l,mid,rt<<1,c[rt]);
        color(mid+1,r,rt<<1|1,c[rt]);
        c[rt]=0;     
    }
}
void update(int nowl,int nowr,int x,int l,int r,int rt){
    if(nowl<=l&&nowr>=r){
        color(l,r,rt,x);
        return;
    }
    pushc(l,r,rt);  
    int mid=(l+r)>>1;
    if(nowl<=mid)    update(nowl,nowr,x,l,mid,rt<<1);
    if(mid<nowr) update(nowl,nowr,x,mid+1,r,rt<<1|1);
    push(rt);
}
int query(int l,int r,int rt,int nowl,int nowr){
    if(nowl<=l&&r<=nowr) return s[rt];
    pushc(l,r,rt);
    int ans=0;
    int mid=(l+r)>>1;
    if(nowl<=mid) ans+=query(l,mid,rt<<1,nowl,nowr);
    if(nowr>mid) ans+=query(mid+1,r,rt<<1|1,nowl,nowr);
    return ans;
}
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    build(1,n,1);
    for(int i=1;i<=m;i++){
        int opt,x,y;
        scanf("%d%d%d",&opt,&x,&y);
        if(opt==1){
            int v;
            scanf("%d",&v);
            update(x,y,v,1,n,1);
        }
        else{
            cout<<query(1,n,1,x,y)<<endl;
        }
    }
    return 0;
}