PKU 3468 线段树,线段树 第 3 天

/* 线段树第三天,一天一道线段树坚持下去你就是高手*/
/* 终于把一些简单的线段树理解了,明白了 lazy 标记的好处
这是第三天了*/
#include<cstdio>
#include<iostream>
using namespace std;
#define _ long long
#define lson id<<1
#define rson id<<1|1
const _ Max = 500005;
struct line
{
    _ left,right;
    _ sum,mark;;
    _ mid()
    {
        return (left + right) / 2;
    }
}node[Max];
_ a[Max];
void PushUp(_ id) 
{
    node[id].sum = (node[lson].sum + node[rson].sum);
}
void Pushdown(_ id) // 传递 标记
{
    if(node[id].mark)
    {
        node[lson].mark += node[id].mark; // 向下传递标记
        node[rson].mark += node[id].mark;
        node[lson].sum  += (node[lson].right-node[lson].left + 1) * node[id].mark;
        node[rson].sum  += (node[rson].right-node[rson].left + 1) * node[id].mark;
        node[id].mark = 0;
    }
}
void _Build_Tree(_ id,_ l,_ r)
{

    node[id].left = l,node[id].right = r;
    node[id].mark = 0;
    if(l == r)
    {
        node[id].sum = a[r];return;
    }
    _ mid = node[id].mid();
    _Build_Tree(lson,l,mid);
    _Build_Tree(rson,mid+1,r);
    PushUp(id);
}
_ n;
void upside(_ l,_ r,_ c,_ id)
{
    if(node[id].left == l && node[id].right ==r)
    {

        node[id].mark += c;
        node[id].sum += (r - l + 1) * c;
        return ;
    }
    _ mid = node[id].mid();
    Pushdown(id);
    if(l > mid)upside(l,r,c,rson);
    else if(r<=mid)upside(l,r,c,lson);
    else {
        upside(l,mid,c,lson);
        upside(mid+1,r,c,rson);
    }
    PushUp(id);
}
_ sum;
_ seach(_ id,_ l,_ r)
{

    if(l==node[id].left&&r == node[id].right)
    { 
       return node[id].sum;
    }
    Pushdown(id);
    _ mid = node[id].mid();
    if(r <= mid)return seach(lson,l,r);
    else if(l>mid)return seach(rson,l,r);
    else{
            return seach(lson,l,mid) + seach(rson,mid+1,r);
    }
}
int main()
{
    _ n,m;
    _ T,l,r,c,cn = 0;
    char s[19];
    while(~scanf("%lld%lld",&n,&m))
    {
        for(_ i=1;i<=n;i++)
            scanf("%lld",&a[i]);
        _Build_Tree(1,1,n);

        while(m--)
        {
            scanf("%s",s);

            if(s[0] == 'Q')
            {   sum = 0;
                scanf("%lld%lld",&l,&r);
                printf("%lld\n",seach(1,l,r));
            }
            else{
            scanf("%lld %lld %lld",&l,&r,&c);
            upside(l,r,c,1);
        }
        }
    }

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值