线段树区间加模板

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#define LL long long
#define l(x) (x<<1)
#define r(x) ((x<<1)|1)
using namespace std;
struct Tre
{
    LL sum,tag;
}Tr[500100];
LL a[500100];
void update(LL id)
{
    Tr[id].sum=Tr[l(id)].sum+Tr[r(id)].sum;
}
void pushdown(LL l,LL r,LL id)
{
    Tr[r(id)].tag+=Tr[id].tag;
    Tr[l(id)].tag+=Tr[id].tag;
    Tr[id].sum+=(r-l+1)*Tr[id].tag;
    Tr[id].tag=0;
}
void build(LL l,LL r,LL id)
{
    if(l==r)
    {
        Tr[id].sum=a[l];
        return;
    }
    LL mid=(l+r)/2;
    build(mid+1,r,r(id));
    build(l,mid,l(id));
    update(id);
}
void add(LL al,LL ar,LL x,LL l,LL r,LL id)
{
    if(l>ar||r<al) return;
    if(al==l&&ar==r) {Tr[id].tag+=x;return;}
    pushdown(l,r,id);
    LL mid=(r+l)/2;
    if(mid>=al) add(al,min(mid,ar),x,l,mid,l(id));
    if(mid<ar) add(max(mid+1,al),ar,x,mid+1,r,r(id));
    pushdown(l,mid,l(id));
    pushdown(mid+1,r,r(id));
    update(id);
}
LL query(LL al,LL ar,LL l,LL r,LL id)
{
    if(l>r) return 0LL;
    if(al==l&&ar==r) {return Tr[id].tag*(r-l+1)+Tr[id].sum;}
    pushdown(l,r,id);
    LL mid=(r+l)/2;
    LL t=0;
    if(mid>=al) t+=query(al,min(mid,ar),l,mid,l(id));
    if(mid<ar) t+=query(max(mid+1,al),ar,mid+1,r,r(id));
    return t;
}
int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
    build(1,n,1);
    while(m--)
    {
        int cas;
        scanf("%d",&cas);
        if(cas==1)
        {
            LL x,y,k;
            scanf("%lld%lld%lld",&x,&y,&k);
            add(x,y,k,1,n,1);
        }
        else
        {
            LL x,y;
            scanf("%lld%lld",&x,&y);
            printf("%lld\n",query(x,y,1,n,1));
        }
    }
}
区间加

 

posted @ 2017-11-14 20:21  秦こころ酱  阅读(104)  评论(0编辑  收藏  举报