poj 3468 经典线段树

 只要加一个lazy就行了,注意的是update和query里的return条件。只要当前区间包含于查询区间就可以直接返回了。

当时没注意,只在query里设置了,update里没用lazy(汗

#include <queue>
#include <cstdio>
#include <set>
#include <string>
#include <stack>
#include <cmath>
#include <climits>
#include <map>
#include <cstdlib>
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstring>
#include <stdio.h>
#include <ctype.h>
#include <bitset>
#define  LL long long
#define  ULL unsigned long long
#define mod 1000000007
#define INF 0x7ffffff
#define mem(a,b) memset(a,b,sizeof(a))
#define MODD(a,b) (((a%b)+b)%b)
#define maxn 100005
using namespace std;
LL sum[maxn << 2];
LL lazy[maxn << 2];
LL a[maxn];
LL n;
void pushUp(LL rt)
{
    sum[rt] = sum[rt << 1] + sum[rt << 1 | 1];
}
void pushDown(LL ln,LL rn,LL rt)
{
    if(lazy[rt]){
      lazy[rt << 1] += lazy[rt];
      lazy[rt << 1|1] += lazy[rt];
      sum[rt << 1] += lazy[rt] * ln;
      sum[rt << 1|1] += lazy[rt] * rn;
      lazy[rt] = 0;
    }
}
void build_tree(LL left,LL right,LL rt)
{
    if(left == right){
        sum[rt] = a[left];
        return;
    }
    LL mid = (left + right) >> 1;
    build_tree(left , mid , rt << 1);
    build_tree(mid + 1 , right , rt << 1 | 1);
    pushUp(rt);
}
void update(LL L,LL R,LL v,LL left,LL right,LL rt)
{
    if(L <= left && right <= R){
        sum[rt] += v * (right - left + 1);
        lazy[rt] += v;
        return;
    }
    LL mid = (left + right) >> 1;
    pushDown(mid - left + 1,right - mid,rt);
    if(L <= mid) update(L,R,v,left,mid,rt << 1);
    if(R > mid) update(L,R,v,mid + 1,right,rt << 1 | 1);
    pushUp(rt);
}
LL query(LL L,LL R,LL left,LL right,LL rt)
{
    if(L <= left && right <= R){
        return sum[rt];
    }

    LL mid = (left + right) >> 1;
    pushDown(mid - left + 1, right - mid, rt);
    LL ans = 0;
    if(L <= mid) ans += query(L,R,left,mid,rt << 1);
    if(R > mid)  ans += query(L,R,mid + 1,right,rt << 1 | 1);
    return ans;
}
int main()
{
    LL m;
    while(~scanf("%lld%lld",&n,&m)){
      mem(sum,0);
      mem(lazy,0);
      for(LL i = 1; i <= n; i++) scanf("%lld",&a[i]);
      build_tree(1,n,1);
      char c[2];
      LL L,R;
      while(m--){
        //getchar();
        scanf("%s",c);
        if(c[0] == 'Q'){
            scanf("%lld%lld",&L,&R);
            printf("%lld\n",query(L,R,1,n,1));
            /*for(int i = 1; i <= n*4; i++) printf("%d--%d ",i,a[i]);
           printf("\n");
           for(int i = 0; i <= n*4; i++) printf("%d--%d ",i,sum[i]);
           printf("\n");*/
        }
        if(c[0] == 'C'){
           LL v;
           scanf("%lld%lld%lld",&L,&R,&v);
           update(L,R,v,1,n,1);

        }
      }
    }


    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值