线段树模板

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <vector>
#include <string>
#include <cmath>
#include <stack>
#include <queue>
#include <map>
#define lson l,m,i << 1
#define rson m+1,r,i << 1 | 1
#define MAX 0x3f3f3f3f
const int MAXN = 1e5+10;
using namespace std;
typedef long long LL;
struct Node
{
    int l,r;
    int mid()
    {
        return (l+r)/2.0;
    }
};
Node node[MAXN<<2];
LL add[MAXN<<2];                            // 延迟标记数组
LL sum[MAXN<<2];                            //每个节点的sum
void pushup(int i)                          //建树递归返回时更新
{
    sum[i]=sum[i<<1]+sum[i<<1|1];
}
void Build(int l,int r,int i)               //建树并完成初始化
{
    node[i].l=l;
    node[i].r=r;
    sum[i]=0;
    add[i]=0;
    if(l==r)
    {
        scanf("%lld",&sum[i]);             //输入叶子节点
        return ;
    }

    int m=node[i].mid();
    Build(lson);                           //更新父亲节点的值
    Build(rson);
    pushup(i);
}
void pushdown(int i,int L)                 //L为区间长度,延迟标记向下压
{
    if(add[i])
    {
        add[i<<1]+=add[i];
        add[i<<1|1]+=add[i];
        sum[i<<1]+=add[i]*(L-(L>>1));
        sum[i<<1|1]+=add[i]*(L>>1);
        add[i]=0;
    }
}
void update(int v,int l,int r,int i)      //更新l~r,+v
{
    if(node[i].l==l&&node[i].r==r)
    {
        sum[i]+=(LL)v*(r-l+1);            //更新当前节点
        add[i]+=v;                        //延迟标记+v
        return ;
    }
    pushdown(i,node[i].r-node[i].l+1);    //检查这个区间是否有延迟标记
    int m=node[i].mid();
    if(r<=m)
        update(v,l,r,i<<1);
    else
    {
        if(l>m)
            update(v,l,r,i<<1|1);
        else
        {
            update(v,l,m,i<<1);
            update(v,m+1,r,i<<1|1);
        }
    }
    pushup(i);
}
LL M;
void query(int l,int r,int i)                 //查询
{
    if(node[i].l==l&&node[i].r==r)
    {
        M+=sum[i];
        return ;
    }
    pushdown(i,node[i].r-node[i].l+1);
    int m=node[i].mid();
    if(r<=m)
        query(l,r,i<<1);
    else
    {
        if(l>m)
            query(l,r,i<<1|1);
        else
        {
            query(l,m,i<<1);
            query(m+1,r,i<<1|1);
        }
    }
}
int main()
{
    int n,q;
    while(~scanf("%d%d",&n,&q))
    {
        Build(1,n,1);
        while(q--)
        {
            int a,b,c;
            char s;
            cin >> s;
            if(s=='Q')
            {
                M=0;
                scanf("%d%d",&a,&b);
                query(a,b,1);
                printf("%lld\n",M);
            }
            if(s=='C')
            {
                scanf("%d%d%d",&a,&b,&c);
                update(c,a,b,1);
            }
        }
    }

    return 0;
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值