线段树 - 区间加值求区间和

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
using std::cin;
using std::cout;
using std::endl;

typedef long long ll;

const int maxn=524300;
int n,m;
ll tree[maxn];
ll lazy[maxn];

void build(int node = 1, int l = 1, int r = n)
{
    if(l==r)
    {
        scanf("%lld",&tree[node]);
        return;
    }
    int mid=(l+r)/2;
    int lc=node<<1;
    int rc=(node<<1)+1;
    build(lc, l, mid);
    build(rc, mid+1, r);
    tree[node] = tree[lc] + tree[rc];
}

void pushdown(int node, int l, int r)
{
    if(lazy[node])
    {
        int lc=node<<1;
        int rc=(node<<1)+1;
        lazy[lc]+=lazy[node];
        lazy[rc]+=lazy[node];
        int mid=(l+r)/2;
        tree[lc]+=lazy[node] * (mid-l+1);
        tree[rc]+=lazy[node] * (r-mid);
        lazy[node]=0;
    }
}

int g_L,g_R;
ll g_x;
void update(int node = 1, int l = 1, int r = n)
{
    if(g_L<=l && r<=g_R)
    {
        tree[node]+=g_x * (r-l+1);
        lazy[node]+=g_x;
        return;
    }
    int mid=(l+r)/2;
    int lc=node<<1;
    int rc=(node<<1)+1;
    pushdown(node, l, r);

    if(g_L<=mid)
    {
        update(lc,l,mid);
    }
    if(g_R>mid)
    {
        update(rc,mid+1,r);
    }
    tree[node]=tree[lc]+tree[rc];
}

ll query(int node = 1, int l = 1, int r = n)
{
    if(g_L<=l && r<=g_R)
    {
        return tree[node];
    }
    int mid=(l+r)/2;
    int lc=node<<1;
    int rc=(node<<1)+1;
    pushdown(node, l, r);

    ll sum=0;
    if(g_L<=mid)
    {
        sum+=query(lc,l,mid);
    }
    if(g_R>mid)
    {
        sum+=query(rc,mid+1,r);
    }
    return sum;
}

int main()
{
    scanf("%d",&n);
    build();
    scanf("%d",&m);
    while(m--)
    {
        int ins;
        scanf("%d",&ins);
        if(ins==1)
        {
            scanf("%d%d%lld",&g_L,&g_R,&g_x);
            update();
        }
        else if(ins==2)
        {
            scanf("%d%d",&g_L,&g_R);
            printf("%lld\n",query());
        }
    }
    return 0;
}

你可能感兴趣的:(OI)