poj 3468 线段树+懒标记

   简单的线段树区间求和问题,每次改变区间值得时候采用懒标记的操作,等到下次经过这个区间的时候再将懒标记向下传递。

#include <cstdio>
#include <iostream>

using namespace std;

int n,q;
int a[100005];
long long sum[500005],lazy[500005];

void build(int l,int r,int k)
{
    lazy[k]==0;
    if (l==r)
    {
        sum[k]=a[l];
        return;
    }
    int mid=(l+r)>>1;
    build(l,mid,2*k);
    build(mid+1,r,2*k+1);
    sum[k]=sum[2*k]+sum[2*k+1];
}

void pushdown(int m,int k)
{
    if (lazy[k])
    {
        lazy[2*k]+=lazy[k];
        lazy[2*k+1]+=lazy[k];
        sum[2*k]+=(long long)lazy[k]*(m-(m>>1));
        sum[2*k+1]+=(long long)lazy[k]*(m>>1);
        lazy[k]=0;
    }
}

long long work(int l,int r,int k,int L,int R)
{
    if ((L<=l)&&(r<=R))
    {
        return sum[k];
    }
    pushdown(r-l+1,k);
    int mid=(l+r)>>1;
    if (R<=mid) return work(l,mid,2*k,L,R);
    else if (L>mid) return work(mid+1,r,2*k+1,L,R);
    else return work(l,mid,2*k,L,mid)+work(mid+1,r,2*k+1,mid+1,R);
}

void change(int l,int r,int k,int L,int R,int VAL)
{
    if ((L<=l)&&(r<=R))
    {
        lazy[k]+=VAL;
        sum[k]+=(long long)VAL*(R-L+1);
        return;
    }
    pushdown(r-l+1,k);
    int mid=(l+r)>>1;
    if (R<=mid) change(l,mid,2*k,L,R,VAL);
    else if(L>mid) change(mid+1,r,2*k+1,L,R,VAL);
    else
    {
        change(l,mid,2*k,L,mid,VAL);
        change(mid+1,r,2*k+1,mid+1,R,VAL);
    }
    sum[k]=sum[2*k]+sum[2*k+1];
}

int main()
{
    scanf("%d%d",&n,&q);
    for (int i=0;i<n;i++) scanf("%d",&a[i]);
    build(0,n-1,1);
    for (int i=0;i<q;i++)
    {
        char ch[5];
        int a,b,c;
        scanf("%s%d%d",ch,&a,&b);
        a--; b--;
        if (ch[0]=='Q')
        {
            printf("%I64d\n",work(0,n-1,1,a,b));
        }
        else
        {
            scanf("%d",&c);
            change(0,n-1,1,a,b,c);
        }
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值