线段树(建树,单点修改,区间修改(lazy标记),求区间维护值模板)

#define _CRT_SECURE_NO_WARNINGS 
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<cstring>
#include<cmath>
#include<ctime>
#include<algorithm>
#include<utility>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<math.h>
#include<map>
using namespace std;
const int N = 1e5 + 10;
#define ls (o<<1)
#define rs (o<<1|1)
long long  sum[N << 2],a[N];
long long lazy[N << 2];
int n, m;
void pushupsum(int o)
{
    sum[o] = sum[ls] + sum[rs];
}
void build(int o, int l, int r)//建树
{
    if (l == r)
    {
        sum[o] = a[l];
        return;
    }
    int mid=(l+r)>>1;
    build(ls, l, mid);
    build(rs, mid + 1, r);
    pushupsum(o);
}
void  pushdown(int o,int l,int r)//下传lazy标记
{
    if (lazy[o])
    {
        int mid = (l + r) >> 1;
        sum[ls] += (mid - l + 1) * lazy[o];
        sum[rs] += (r - mid) * lazy[o];
        lazy[ls] += lazy[o];
        lazy[rs] += lazy[o];
        lazy[o] = 0;
        return;
    }
}
void change(int o, int l, int r, int x, int ql, int qr)//区间修改
{   
    if (ql <= l && qr >= r)
    {
        sum[o] += x * (r - l + 1);
        lazy[o] += x;
        return;
    }
    pushdown(o,l,r);
    int mid = (l + r) >> 1;
    if (ql <= mid)
        change(ls, l, mid,x,ql, qr);
    if (qr > mid)
        change(rs, mid + 1, r, x, ql, qr);
    pushupsum(o);
}
long long ask(int o, int l, int r, int ql, int qr)//求区间维护值
{
    if (ql <= l && qr >= r)
    {
        return sum[o];
    }
    pushdown(o, l, r);
    long long ans = 0;
    int mid = (l + r) >> 1;
    if (ql <= mid)
       ans+=ask(ls, l, mid, ql, qr);
    if (qr > mid)
       ans+=ask(rs, mid + 1, r,ql, qr);
    return ans;
}
void modify(int o, int l, int r, int x, int v)//单点修改
{
    if (l == r && l == x)
    {
        sum[o] = v;
        return;
    }
    pushdown(o, l, r);
    int mid = (l + r) >> 1;
    if (x <= mid)
        modify(ls, l, mid, x, v);
    else
        modify(rs, mid + 1, r, x, v);
    sum[o] += sum[ls] + sum[rs];
 }
int main()
{
    scanf("%d%d", &n, &m);
    memset(lazy, 0, sizeof lazy);
    for (int i = 1; i <= n; i++)
       scanf("%lld",&a[i]);
    build(1, 1, n);
    for (int i = 1; i <= m; i++)
    {
        int k,ql,qr;
        scanf("%d", &k);
        if (k == 1)
        {
            scanf("%d%d%d",&ql, &qr,&k);
            change(1, 1, n, k, ql, qr);
        }
        else
        {
            scanf("%d%d",&ql, &qr);
            printf("%lld\n", ask(1, 1, n, ql, qr));
        }
    }
    return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值