线段树1(区间懒标记) 洛谷3372

感动,,我这个菜鸟把困扰多时的线段树干掉了(wanna cry),留给日后作纪念

#pragma GCC optimize(3)
#include <bits/stdc++.h>
#define rep(i,x,y) for(int i=x;i<=y;i++)
using namespace std;
typedef long long ll;
int read(){
    int x=0,f=1;char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
    while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
    return x*f;
}
const int maxn=100500;
ll a[maxn];
ll sum[maxn<<2],tag[maxn<<2];
ll n,m;
ll SUM;
void pushup(int k){
    sum[k]=sum[k<<1]+sum[k<<1|1];}
void pushdown(int k,int l,int r,int mid){
    if(!tag[k]) return;
    int v=tag[k];
    tag[k<<1]+=v;sum[k<<1]+=(mid-l+1)*v;
    tag[k<<1|1]+=v;sum[k<<1|1]+=(r-mid)*v;
    tag[k]=0;
}
void update(int k,int l,int r,int x,int y,int v){
    if(x<=l&&r<=y){sum[k]+=v*(r-l+1);tag[k]+=v;return;}
    int mid=(l+r)>>1;
    pushdown(k,l,r,mid);
    if(x<=mid) update(k<<1,l,mid,x,y,v);
    if(mid<y) update(k<<1|1,mid+1,r,x,y,v);
    pushup(k);
}
void build(int k,int l,int r){
    if(l==r){sum[k]=a[l];return;}
    int mid=(l+r)>>1;
    build(k<<1,l,mid);
    build(k<<1|1,mid+1,r);
    pushup(k);
}
void query(int k,int l,int r,int x,int y){
    if(x<=l&&r<=y){SUM+=sum[k];return;}
    int mid=(l+r)>>1;
    pushdown(k,l,r,mid);
    if(x<=mid) query(k<<1,l,mid,x,y);
    if(mid<y) query(k<<1|1,mid+1,r,x,y);
}
int main(){
    n=(ll)read(),m=(ll)read();
    rep(i,1,n) a[i]=read();
    build(1,1,n);
    rep(i,1,m){
        int t=read(),x,y,k;
        if(t==1){
            x=read(),y=read(),k=read();
            update(1,1,n,x,y,k);
        }else if(t==2){
            x=read(),y=read();
            SUM=0;
            query(1,1,n,x,y);
            printf("%lld\n",SUM);
        }
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/asdic/p/9424719.html