poj(3468)セグメントツリーlazy操作

2675 ワード

标题:区間毎の数に1つの数を加えて、1つの区間の和を尋ねる.
#include <queue>
#include <stack>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <limits.h>
#include <string.h>
#include <algorithm>
#define LL long long
#define ls rt<<1
#define rs rt<<1|1
#define lson L,m,rt<<1
#define rson m+1,R,rt<<1|1
#define make_m int m=(L+R)/2;
using namespace std;
const LL N=100005;
struct Node
{
    LL L,R;
    LL lazy;
    LL sum;
}tree[N*4];
LL n,q;
void up(LL rt)
{
    tree[rt].sum=(tree[ls].sum+tree[rs].sum);
}
void down(LL rt,LL c)
{
    if(tree[rt].lazy)
    {
        tree[ls].lazy+=tree[rt].lazy;
        tree[rs].lazy+=tree[rt].lazy;
        tree[ls].sum+=(c-c/2)*tree[rt].lazy;
        tree[rs].sum+=(c/2)*tree[rt].lazy;
        tree[rt].lazy=0;
    }
}
void built(LL L,LL R,LL rt)
{
    tree[rt].lazy=0;
    tree[rt].L=L;
    tree[rt].R=R;
    tree[rt].sum=0;
    if(L==R)
    {
        scanf("%lld",&tree[rt].sum);
        return ;
    }
    make_m;
    built(lson);
    built(rson);
    up(rt);
}

void update(LL l,LL r,LL c,LL rt)
{
    LL L=tree[rt].L;
    LL R=tree[rt].R;
    if(L>=l&&R<=r)
    {
        tree[rt].lazy+=c;
        tree[rt].sum+=(LL)c*(R-L+1);
        return ;
    }
    down(rt,R-L+1);
    make_m;
    if(l<=m)
    update(l,r,c,ls);
    if(r>m)
    update(l,r,c,rs);
    up(rt);
}
LL query(LL l,LL r,LL rt)
{
    LL L=tree[rt].L;
    LL R=tree[rt].R;
    if(L>=l&&R<=r)
    {
        return tree[rt].sum;
    }
    make_m;
    down(rt,R-L+1);
    LL ans=0;
    if(l<=m)
    ans+=query(l,r,ls);
    if(r>m)
    ans+=query(l,r,rs);
    return ans;
}
int main()
{
    LL L,R,c;
    char ch[20];
    scanf("%lld%lld",&n,&q);
    built(1,n,1);
    while(q--)
    {
        scanf("%s",ch);
      if(ch[0]=='Q')
        scanf("%lld%lld",&L,&R), cout<<query(L,R,1)<<endl;
      else
        scanf("%lld%lld%lld",&L,&R,&c),update(L,R,c,1);
    }
    return 0;
}